Previous 199869 Revisions Next

r40683 Saturday 12th September, 2015 at 08:12:14 UTC by Miodrag Milanović
Moved netlist from emu to lib (nw)
[scripts/src]emu.lua netlist.lua tools.lua
[scripts/target/mame]arcade.lua mess.lua nl.lua
[src/build]makedep.py
[src/emu/netlist]nl_base.c nl_base.h nl_config.h nl_dice_compat.h nl_factory.c nl_factory.h nl_lists.h nl_parser.c nl_parser.h nl_setup.c nl_setup.h nl_time.h nl_util.h
[src/emu/netlist/analog]nld_bjt.c nld_bjt.h nld_fourterm.c nld_fourterm.h nld_opamps.c nld_opamps.h nld_switches.c nld_switches.h nld_twoterm.c nld_twoterm.h
[src/emu/netlist/build]makefile
[src/emu/netlist/devices]net_lib.c net_lib.h nld_4020.c nld_4020.h nld_4066.c nld_4066.h nld_7400.c nld_7400.h nld_7402.c nld_7402.h nld_7404.c nld_7404.h nld_7408.c nld_7408.h nld_7410.c nld_7410.h nld_74107.c nld_74107.h nld_7411.c nld_7411.h nld_74123.c nld_74123.h nld_74153.c nld_74153.h nld_74175.c nld_74175.h nld_74192.c nld_74192.h nld_74193.c nld_74193.h nld_7420.c nld_7420.h nld_7425.c nld_7425.h nld_7427.c nld_7427.h nld_74279.c nld_74279.h nld_7430.c nld_7430.h nld_7432.c nld_7432.h nld_7437.c nld_7437.h nld_7448.c nld_7448.h nld_7450.c nld_7450.h nld_7474.c nld_7474.h nld_7483.c nld_7483.h nld_7486.c nld_7486.h nld_7490.c nld_7490.h nld_7493.c nld_7493.h nld_74ls629.c nld_74ls629.h nld_82S16.c nld_82S16.h nld_9310.c nld_9310.h nld_9312.c nld_9312.h nld_9316.c nld_9316.h nld_cmos.h nld_legacy.c nld_legacy.h nld_log.c nld_log.h nld_mm5837.c nld_mm5837.h nld_ne555.c nld_ne555.h nld_r2r_dac.c nld_r2r_dac.h nld_signal.h nld_system.c nld_system.h nld_truthtable.c nld_truthtable.h
[src/emu/netlist/macro]nlm_cd4xxx.c nlm_cd4xxx.h nlm_opamp.c nlm_opamp.h nlm_other.c nlm_other.h nlm_ttl74xx.c nlm_ttl74xx.h
[src/emu/netlist/plib]palloc.c palloc.h pconfig.h plists.h poptions.h pparser.c pparser.h pstate.c pstate.h pstream.c pstream.h pstring.c pstring.h
[src/emu/netlist/prg]nltool.c nlwav.c
[src/emu/netlist/solver]mat_cr.h nld_ms_direct.h nld_ms_direct1.h nld_ms_direct2.h nld_ms_direct_lu.h nld_ms_gmres.h nld_ms_sor.h nld_ms_sor_mat.h nld_solver.c nld_solver.h vector_base.h
[src/emu/netlist/tools]nl_convert.c nl_convert.h
[src/lib/netlist]nl_base.c* nl_base.h* nl_config.h* nl_dice_compat.h* nl_factory.c* nl_factory.h* nl_lists.h* nl_parser.c* nl_parser.h* nl_setup.c* nl_setup.h* nl_time.h* nl_util.h*
[src/lib/netlist/analog]nld_bjt.c* nld_bjt.h* nld_fourterm.c* nld_fourterm.h* nld_opamps.c* nld_opamps.h* nld_switches.c* nld_switches.h* nld_twoterm.c* nld_twoterm.h*
[src/lib/netlist/build]makefile*
[src/lib/netlist/devices]net_lib.c* net_lib.h* nld_4020.c* nld_4020.h* nld_4066.c* nld_4066.h* nld_7400.c* nld_7400.h* nld_7402.c* nld_7402.h* nld_7404.c* nld_7404.h* nld_7408.c* nld_7408.h* nld_7410.c* nld_7410.h* nld_74107.c* nld_74107.h* nld_7411.c* nld_7411.h* nld_74123.c* nld_74123.h* nld_74153.c* nld_74153.h* nld_74175.c* nld_74175.h* nld_74192.c* nld_74192.h* nld_74193.c* nld_74193.h* nld_7420.c* nld_7420.h* nld_7425.c* nld_7425.h* nld_7427.c* nld_7427.h* nld_74279.c* nld_74279.h* nld_7430.c* nld_7430.h* nld_7432.c* nld_7432.h* nld_7437.c* nld_7437.h* nld_7448.c* nld_7448.h* nld_7450.c* nld_7450.h* nld_7474.c* nld_7474.h* nld_7483.c* nld_7483.h* nld_7486.c* nld_7486.h* nld_7490.c* nld_7490.h* nld_7493.c* nld_7493.h* nld_74ls629.c* nld_74ls629.h* nld_82S16.c* nld_82S16.h* nld_9310.c* nld_9310.h* nld_9312.c* nld_9312.h* nld_9316.c* nld_9316.h* nld_cmos.h* nld_legacy.c* nld_legacy.h* nld_log.c* nld_log.h* nld_mm5837.c* nld_mm5837.h* nld_ne555.c* nld_ne555.h* nld_r2r_dac.c* nld_r2r_dac.h* nld_signal.h* nld_system.c* nld_system.h* nld_truthtable.c* nld_truthtable.h*
[src/lib/netlist/macro]nlm_cd4xxx.c* nlm_cd4xxx.h* nlm_opamp.c* nlm_opamp.h* nlm_other.c* nlm_other.h* nlm_ttl74xx.c* nlm_ttl74xx.h*
[src/lib/netlist/plib]palloc.c* palloc.h* pconfig.h* plists.h* poptions.h* pparser.c* pparser.h* pstate.c* pstate.h* pstream.c* pstream.h* pstring.c* pstring.h*
[src/lib/netlist/prg]nltool.c* nlwav.c*
[src/lib/netlist/solver]mat_cr.h* nld_ms_direct.h* nld_ms_direct1.h* nld_ms_direct2.h* nld_ms_direct_lu.h* nld_ms_gmres.h* nld_ms_sor.h* nld_ms_sor_mat.h* nld_solver.c* nld_solver.h* vector_base.h*
[src/lib/netlist/tools]nl_convert.c* nl_convert.h*

trunk/scripts/src/emu.lua
r249194r249195
379379   includedirs {
380380      MAME_DIR .. "src/osd",
381381      MAME_DIR .. "src/emu",
382    MAME_DIR .. "src/emu/netlist",
382      MAME_DIR .. "src/lib/netlist",
383383      MAME_DIR .. "src/mame", -- used for sound amiga
384384      MAME_DIR .. "src/lib",
385385      MAME_DIR .. "src/lib/util",
r249194r249195
426426   includedirs {
427427      MAME_DIR .. "src/osd",
428428      MAME_DIR .. "src/emu",
429    MAME_DIR .. "src/emu/netlist",
429      MAME_DIR .. "src/lib/netlist",
430430      MAME_DIR .. "src/lib",
431431      MAME_DIR .. "src/lib/util",
432432      MAME_DIR .. "3rdparty",
trunk/scripts/src/netlist.lua
r249194r249195
1010   }
1111
1212   includedirs {
13      MAME_DIR .. "src/emu/netlist",
13      MAME_DIR .. "src/lib/netlist",
1414      MAME_DIR .. "src/osd",
1515      MAME_DIR .. "src/lib/util",
1616   }
r249194r249195
2222
2323
2424   files {
25      MAME_DIR .. "src/emu/netlist/nl_config.h",
26      MAME_DIR .. "src/emu/netlist/nl_dice_compat.h",
27      MAME_DIR .. "src/emu/netlist/nl_lists.h",
28      MAME_DIR .. "src/emu/netlist/nl_time.h",
29      MAME_DIR .. "src/emu/netlist/nl_util.h",
30      MAME_DIR .. "src/emu/netlist/nl_base.c",
31      MAME_DIR .. "src/emu/netlist/nl_base.h",
32      MAME_DIR .. "src/emu/netlist/nl_parser.c",
33      MAME_DIR .. "src/emu/netlist/nl_parser.h",
34      MAME_DIR .. "src/emu/netlist/nl_setup.c",
35      MAME_DIR .. "src/emu/netlist/nl_setup.h",
36      MAME_DIR .. "src/emu/netlist/nl_factory.c",
37      MAME_DIR .. "src/emu/netlist/nl_factory.h",
38      MAME_DIR .. "src/emu/netlist/plib/pconfig.h",
39      MAME_DIR .. "src/emu/netlist/plib/palloc.c",
40      MAME_DIR .. "src/emu/netlist/plib/palloc.h",
41      MAME_DIR .. "src/emu/netlist/plib/plists.h",
42      MAME_DIR .. "src/emu/netlist/plib/poptions.h",
43      MAME_DIR .. "src/emu/netlist/plib/pparser.c",
44      MAME_DIR .. "src/emu/netlist/plib/pparser.h",
45      MAME_DIR .. "src/emu/netlist/plib/pstate.c",
46      MAME_DIR .. "src/emu/netlist/plib/pstate.h",
47      MAME_DIR .. "src/emu/netlist/plib/pstring.c",
48      MAME_DIR .. "src/emu/netlist/plib/pstring.h",
49      MAME_DIR .. "src/emu/netlist/plib/pstring.c",
50      MAME_DIR .. "src/emu/netlist/plib/pstring.h",
51    MAME_DIR .. "src/emu/netlist/plib/pstream.c",
52    MAME_DIR .. "src/emu/netlist/plib/pstream.h",
53      MAME_DIR .. "src/emu/netlist/tools/nl_convert.c",
54      MAME_DIR .. "src/emu/netlist/tools/nl_convert.h",
55      MAME_DIR .. "src/emu/netlist/analog/nld_bjt.c",
56      MAME_DIR .. "src/emu/netlist/analog/nld_bjt.h",
57      MAME_DIR .. "src/emu/netlist/analog/nld_fourterm.c",
58      MAME_DIR .. "src/emu/netlist/analog/nld_fourterm.h",
59      MAME_DIR .. "src/emu/netlist/analog/nld_switches.c",
60      MAME_DIR .. "src/emu/netlist/analog/nld_switches.h",
61      MAME_DIR .. "src/emu/netlist/analog/nld_twoterm.c",
62      MAME_DIR .. "src/emu/netlist/analog/nld_twoterm.h",
63      MAME_DIR .. "src/emu/netlist/analog/nld_opamps.c",
64      MAME_DIR .. "src/emu/netlist/analog/nld_opamps.h",
65    MAME_DIR .. "src/emu/netlist/solver/nld_solver.c",
66    MAME_DIR .. "src/emu/netlist/solver/nld_solver.h",
67      MAME_DIR .. "src/emu/netlist/solver/nld_ms_direct.h",
68      MAME_DIR .. "src/emu/netlist/solver/nld_ms_direct1.h",
69      MAME_DIR .. "src/emu/netlist/solver/nld_ms_direct2.h",
70      MAME_DIR .. "src/emu/netlist/solver/nld_ms_sor.h",
71    MAME_DIR .. "src/emu/netlist/solver/nld_ms_sor_math.h",
72    MAME_DIR .. "src/emu/netlist/solver/nld_ms_gmres.h",
73      MAME_DIR .. "src/emu/netlist/devices/nld_4020.c",
74      MAME_DIR .. "src/emu/netlist/devices/nld_4020.h",
75      MAME_DIR .. "src/emu/netlist/devices/nld_4066.c",
76      MAME_DIR .. "src/emu/netlist/devices/nld_4066.h",
77      MAME_DIR .. "src/emu/netlist/devices/nld_7400.c",
78      MAME_DIR .. "src/emu/netlist/devices/nld_7400.h",
79      MAME_DIR .. "src/emu/netlist/devices/nld_7402.c",
80      MAME_DIR .. "src/emu/netlist/devices/nld_7402.h",
81      MAME_DIR .. "src/emu/netlist/devices/nld_7404.c",
82      MAME_DIR .. "src/emu/netlist/devices/nld_7404.h",
83      MAME_DIR .. "src/emu/netlist/devices/nld_7408.c",
84      MAME_DIR .. "src/emu/netlist/devices/nld_7408.h",
85      MAME_DIR .. "src/emu/netlist/devices/nld_7410.c",
86      MAME_DIR .. "src/emu/netlist/devices/nld_7410.h",
87      MAME_DIR .. "src/emu/netlist/devices/nld_7411.c",
88      MAME_DIR .. "src/emu/netlist/devices/nld_7411.h",
89      MAME_DIR .. "src/emu/netlist/devices/nld_7420.c",
90      MAME_DIR .. "src/emu/netlist/devices/nld_7420.h",
91      MAME_DIR .. "src/emu/netlist/devices/nld_7425.c",
92      MAME_DIR .. "src/emu/netlist/devices/nld_7425.h",
93      MAME_DIR .. "src/emu/netlist/devices/nld_7427.c",
94      MAME_DIR .. "src/emu/netlist/devices/nld_7427.h",
95      MAME_DIR .. "src/emu/netlist/devices/nld_7430.c",
96      MAME_DIR .. "src/emu/netlist/devices/nld_7430.h",
97      MAME_DIR .. "src/emu/netlist/devices/nld_7432.c",
98      MAME_DIR .. "src/emu/netlist/devices/nld_7432.h",
99      MAME_DIR .. "src/emu/netlist/devices/nld_7437.c",
100      MAME_DIR .. "src/emu/netlist/devices/nld_7437.h",
101      MAME_DIR .. "src/emu/netlist/devices/nld_7448.c",
102      MAME_DIR .. "src/emu/netlist/devices/nld_7448.h",
103      MAME_DIR .. "src/emu/netlist/devices/nld_7450.c",
104      MAME_DIR .. "src/emu/netlist/devices/nld_7450.h",
105      MAME_DIR .. "src/emu/netlist/devices/nld_7474.c",
106      MAME_DIR .. "src/emu/netlist/devices/nld_7474.h",
107      MAME_DIR .. "src/emu/netlist/devices/nld_7483.c",
108      MAME_DIR .. "src/emu/netlist/devices/nld_7483.h",
109      MAME_DIR .. "src/emu/netlist/devices/nld_7486.c",
110      MAME_DIR .. "src/emu/netlist/devices/nld_7486.h",
111      MAME_DIR .. "src/emu/netlist/devices/nld_7490.c",
112      MAME_DIR .. "src/emu/netlist/devices/nld_7490.h",
113      MAME_DIR .. "src/emu/netlist/devices/nld_7493.c",
114      MAME_DIR .. "src/emu/netlist/devices/nld_7493.h",
115      MAME_DIR .. "src/emu/netlist/devices/nld_74107.c",
116      MAME_DIR .. "src/emu/netlist/devices/nld_74107.h",
117      MAME_DIR .. "src/emu/netlist/devices/nld_74123.c",
118      MAME_DIR .. "src/emu/netlist/devices/nld_74123.h",
119      MAME_DIR .. "src/emu/netlist/devices/nld_74153.c",
120      MAME_DIR .. "src/emu/netlist/devices/nld_74153.h",
121      MAME_DIR .. "src/emu/netlist/devices/nld_74175.c",
122      MAME_DIR .. "src/emu/netlist/devices/nld_74175.h",
123      MAME_DIR .. "src/emu/netlist/devices/nld_74192.c",
124      MAME_DIR .. "src/emu/netlist/devices/nld_74192.h",
125      MAME_DIR .. "src/emu/netlist/devices/nld_74193.c",
126      MAME_DIR .. "src/emu/netlist/devices/nld_74193.h",
127      MAME_DIR .. "src/emu/netlist/devices/nld_74279.c",
128      MAME_DIR .. "src/emu/netlist/devices/nld_74279.h",
129      MAME_DIR .. "src/emu/netlist/devices/nld_74ls629.c",
130      MAME_DIR .. "src/emu/netlist/devices/nld_74ls629.h",
131      MAME_DIR .. "src/emu/netlist/devices/nld_82S16.c",
132      MAME_DIR .. "src/emu/netlist/devices/nld_82S16.h",
133      MAME_DIR .. "src/emu/netlist/devices/nld_9310.c",
134      MAME_DIR .. "src/emu/netlist/devices/nld_9310.h",
135      MAME_DIR .. "src/emu/netlist/devices/nld_9312.c",
136      MAME_DIR .. "src/emu/netlist/devices/nld_9312.h",
137      MAME_DIR .. "src/emu/netlist/devices/nld_9316.c",
138      MAME_DIR .. "src/emu/netlist/devices/nld_9316.h",
139      MAME_DIR .. "src/emu/netlist/devices/nld_ne555.c",
140      MAME_DIR .. "src/emu/netlist/devices/nld_ne555.h",
141    MAME_DIR .. "src/emu/netlist/devices/nld_mm5837.c",
142    MAME_DIR .. "src/emu/netlist/devices/nld_mm5837.h",
143      MAME_DIR .. "src/emu/netlist/devices/nld_r2r_dac.c",
144      MAME_DIR .. "src/emu/netlist/devices/nld_r2r_dac.h",
145      MAME_DIR .. "src/emu/netlist/devices/nld_legacy.c",
146      MAME_DIR .. "src/emu/netlist/devices/nld_legacy.h",
147      MAME_DIR .. "src/emu/netlist/devices/net_lib.c",
148      MAME_DIR .. "src/emu/netlist/devices/net_lib.h",
149      MAME_DIR .. "src/emu/netlist/devices/nld_log.c",
150      MAME_DIR .. "src/emu/netlist/devices/nld_log.h",
151      MAME_DIR .. "src/emu/netlist/devices/nld_system.c",
152      MAME_DIR .. "src/emu/netlist/devices/nld_system.h",
153      MAME_DIR .. "src/emu/netlist/devices/nld_cmos.h",
154      MAME_DIR .. "src/emu/netlist/devices/nld_signal.h",
155      MAME_DIR .. "src/emu/netlist/devices/nld_truthtable.c",
156      MAME_DIR .. "src/emu/netlist/devices/nld_truthtable.h",
157    MAME_DIR .. "src/emu/netlist/macro/nlm_ttl74xx.c",
158    MAME_DIR .. "src/emu/netlist/macro/nlm_ttl74xx.h",
159    MAME_DIR .. "src/emu/netlist/macro/nlm_cd4xxx.c",
160    MAME_DIR .. "src/emu/netlist/macro/nlm_cd4xxx.h",
161    MAME_DIR .. "src/emu/netlist/macro/nlm_opamp.c",
162    MAME_DIR .. "src/emu/netlist/macro/nlm_opamp.h",
163    MAME_DIR .. "src/emu/netlist/macro/nlm_other.c",
164    MAME_DIR .. "src/emu/netlist/macro/nlm_other.h",
25      MAME_DIR .. "src/lib/netlist/nl_config.h",
26      MAME_DIR .. "src/lib/netlist/nl_dice_compat.h",
27      MAME_DIR .. "src/lib/netlist/nl_lists.h",
28      MAME_DIR .. "src/lib/netlist/nl_time.h",
29      MAME_DIR .. "src/lib/netlist/nl_util.h",
30      MAME_DIR .. "src/lib/netlist/nl_base.c",
31      MAME_DIR .. "src/lib/netlist/nl_base.h",
32      MAME_DIR .. "src/lib/netlist/nl_parser.c",
33      MAME_DIR .. "src/lib/netlist/nl_parser.h",
34      MAME_DIR .. "src/lib/netlist/nl_setup.c",
35      MAME_DIR .. "src/lib/netlist/nl_setup.h",
36      MAME_DIR .. "src/lib/netlist/nl_factory.c",
37      MAME_DIR .. "src/lib/netlist/nl_factory.h",
38      MAME_DIR .. "src/lib/netlist/plib/pconfig.h",
39      MAME_DIR .. "src/lib/netlist/plib/palloc.c",
40      MAME_DIR .. "src/lib/netlist/plib/palloc.h",
41      MAME_DIR .. "src/lib/netlist/plib/plists.h",
42      MAME_DIR .. "src/lib/netlist/plib/poptions.h",
43      MAME_DIR .. "src/lib/netlist/plib/pparser.c",
44      MAME_DIR .. "src/lib/netlist/plib/pparser.h",
45      MAME_DIR .. "src/lib/netlist/plib/pstate.c",
46      MAME_DIR .. "src/lib/netlist/plib/pstate.h",
47      MAME_DIR .. "src/lib/netlist/plib/pstring.c",
48      MAME_DIR .. "src/lib/netlist/plib/pstring.h",
49      MAME_DIR .. "src/lib/netlist/plib/pstring.c",
50      MAME_DIR .. "src/lib/netlist/plib/pstring.h",
51      MAME_DIR .. "src/lib/netlist/plib/pstream.c",
52      MAME_DIR .. "src/lib/netlist/plib/pstream.h",
53      MAME_DIR .. "src/lib/netlist/tools/nl_convert.c",
54      MAME_DIR .. "src/lib/netlist/tools/nl_convert.h",
55      MAME_DIR .. "src/lib/netlist/analog/nld_bjt.c",
56      MAME_DIR .. "src/lib/netlist/analog/nld_bjt.h",
57      MAME_DIR .. "src/lib/netlist/analog/nld_fourterm.c",
58      MAME_DIR .. "src/lib/netlist/analog/nld_fourterm.h",
59      MAME_DIR .. "src/lib/netlist/analog/nld_switches.c",
60      MAME_DIR .. "src/lib/netlist/analog/nld_switches.h",
61      MAME_DIR .. "src/lib/netlist/analog/nld_twoterm.c",
62      MAME_DIR .. "src/lib/netlist/analog/nld_twoterm.h",
63      MAME_DIR .. "src/lib/netlist/analog/nld_opamps.c",
64      MAME_DIR .. "src/lib/netlist/analog/nld_opamps.h",
65      MAME_DIR .. "src/lib/netlist/solver/nld_solver.c",
66      MAME_DIR .. "src/lib/netlist/solver/nld_solver.h",
67      MAME_DIR .. "src/lib/netlist/solver/nld_ms_direct.h",
68      MAME_DIR .. "src/lib/netlist/solver/nld_ms_direct1.h",
69      MAME_DIR .. "src/lib/netlist/solver/nld_ms_direct2.h",
70      MAME_DIR .. "src/lib/netlist/solver/nld_ms_sor.h",
71      MAME_DIR .. "src/lib/netlist/solver/nld_ms_sor_math.h",
72      MAME_DIR .. "src/lib/netlist/solver/nld_ms_gmres.h",
73      MAME_DIR .. "src/lib/netlist/devices/nld_4020.c",
74      MAME_DIR .. "src/lib/netlist/devices/nld_4020.h",
75      MAME_DIR .. "src/lib/netlist/devices/nld_4066.c",
76      MAME_DIR .. "src/lib/netlist/devices/nld_4066.h",
77      MAME_DIR .. "src/lib/netlist/devices/nld_7400.c",
78      MAME_DIR .. "src/lib/netlist/devices/nld_7400.h",
79      MAME_DIR .. "src/lib/netlist/devices/nld_7402.c",
80      MAME_DIR .. "src/lib/netlist/devices/nld_7402.h",
81      MAME_DIR .. "src/lib/netlist/devices/nld_7404.c",
82      MAME_DIR .. "src/lib/netlist/devices/nld_7404.h",
83      MAME_DIR .. "src/lib/netlist/devices/nld_7408.c",
84      MAME_DIR .. "src/lib/netlist/devices/nld_7408.h",
85      MAME_DIR .. "src/lib/netlist/devices/nld_7410.c",
86      MAME_DIR .. "src/lib/netlist/devices/nld_7410.h",
87      MAME_DIR .. "src/lib/netlist/devices/nld_7411.c",
88      MAME_DIR .. "src/lib/netlist/devices/nld_7411.h",
89      MAME_DIR .. "src/lib/netlist/devices/nld_7420.c",
90      MAME_DIR .. "src/lib/netlist/devices/nld_7420.h",
91      MAME_DIR .. "src/lib/netlist/devices/nld_7425.c",
92      MAME_DIR .. "src/lib/netlist/devices/nld_7425.h",
93      MAME_DIR .. "src/lib/netlist/devices/nld_7427.c",
94      MAME_DIR .. "src/lib/netlist/devices/nld_7427.h",
95      MAME_DIR .. "src/lib/netlist/devices/nld_7430.c",
96      MAME_DIR .. "src/lib/netlist/devices/nld_7430.h",
97      MAME_DIR .. "src/lib/netlist/devices/nld_7432.c",
98      MAME_DIR .. "src/lib/netlist/devices/nld_7432.h",
99      MAME_DIR .. "src/lib/netlist/devices/nld_7437.c",
100      MAME_DIR .. "src/lib/netlist/devices/nld_7437.h",
101      MAME_DIR .. "src/lib/netlist/devices/nld_7448.c",
102      MAME_DIR .. "src/lib/netlist/devices/nld_7448.h",
103      MAME_DIR .. "src/lib/netlist/devices/nld_7450.c",
104      MAME_DIR .. "src/lib/netlist/devices/nld_7450.h",
105      MAME_DIR .. "src/lib/netlist/devices/nld_7474.c",
106      MAME_DIR .. "src/lib/netlist/devices/nld_7474.h",
107      MAME_DIR .. "src/lib/netlist/devices/nld_7483.c",
108      MAME_DIR .. "src/lib/netlist/devices/nld_7483.h",
109      MAME_DIR .. "src/lib/netlist/devices/nld_7486.c",
110      MAME_DIR .. "src/lib/netlist/devices/nld_7486.h",
111      MAME_DIR .. "src/lib/netlist/devices/nld_7490.c",
112      MAME_DIR .. "src/lib/netlist/devices/nld_7490.h",
113      MAME_DIR .. "src/lib/netlist/devices/nld_7493.c",
114      MAME_DIR .. "src/lib/netlist/devices/nld_7493.h",
115      MAME_DIR .. "src/lib/netlist/devices/nld_74107.c",
116      MAME_DIR .. "src/lib/netlist/devices/nld_74107.h",
117      MAME_DIR .. "src/lib/netlist/devices/nld_74123.c",
118      MAME_DIR .. "src/lib/netlist/devices/nld_74123.h",
119      MAME_DIR .. "src/lib/netlist/devices/nld_74153.c",
120      MAME_DIR .. "src/lib/netlist/devices/nld_74153.h",
121      MAME_DIR .. "src/lib/netlist/devices/nld_74175.c",
122      MAME_DIR .. "src/lib/netlist/devices/nld_74175.h",
123      MAME_DIR .. "src/lib/netlist/devices/nld_74192.c",
124      MAME_DIR .. "src/lib/netlist/devices/nld_74192.h",
125      MAME_DIR .. "src/lib/netlist/devices/nld_74193.c",
126      MAME_DIR .. "src/lib/netlist/devices/nld_74193.h",
127      MAME_DIR .. "src/lib/netlist/devices/nld_74279.c",
128      MAME_DIR .. "src/lib/netlist/devices/nld_74279.h",
129      MAME_DIR .. "src/lib/netlist/devices/nld_74ls629.c",
130      MAME_DIR .. "src/lib/netlist/devices/nld_74ls629.h",
131      MAME_DIR .. "src/lib/netlist/devices/nld_82S16.c",
132      MAME_DIR .. "src/lib/netlist/devices/nld_82S16.h",
133      MAME_DIR .. "src/lib/netlist/devices/nld_9310.c",
134      MAME_DIR .. "src/lib/netlist/devices/nld_9310.h",
135      MAME_DIR .. "src/lib/netlist/devices/nld_9312.c",
136      MAME_DIR .. "src/lib/netlist/devices/nld_9312.h",
137      MAME_DIR .. "src/lib/netlist/devices/nld_9316.c",
138      MAME_DIR .. "src/lib/netlist/devices/nld_9316.h",
139      MAME_DIR .. "src/lib/netlist/devices/nld_ne555.c",
140      MAME_DIR .. "src/lib/netlist/devices/nld_ne555.h",
141      MAME_DIR .. "src/lib/netlist/devices/nld_mm5837.c",
142      MAME_DIR .. "src/lib/netlist/devices/nld_mm5837.h",
143      MAME_DIR .. "src/lib/netlist/devices/nld_r2r_dac.c",
144      MAME_DIR .. "src/lib/netlist/devices/nld_r2r_dac.h",
145      MAME_DIR .. "src/lib/netlist/devices/nld_legacy.c",
146      MAME_DIR .. "src/lib/netlist/devices/nld_legacy.h",
147      MAME_DIR .. "src/lib/netlist/devices/net_lib.c",
148      MAME_DIR .. "src/lib/netlist/devices/net_lib.h",
149      MAME_DIR .. "src/lib/netlist/devices/nld_log.c",
150      MAME_DIR .. "src/lib/netlist/devices/nld_log.h",
151      MAME_DIR .. "src/lib/netlist/devices/nld_system.c",
152      MAME_DIR .. "src/lib/netlist/devices/nld_system.h",
153      MAME_DIR .. "src/lib/netlist/devices/nld_cmos.h",
154      MAME_DIR .. "src/lib/netlist/devices/nld_signal.h",
155      MAME_DIR .. "src/lib/netlist/devices/nld_truthtable.c",
156      MAME_DIR .. "src/lib/netlist/devices/nld_truthtable.h",
157      MAME_DIR .. "src/lib/netlist/macro/nlm_ttl74xx.c",
158      MAME_DIR .. "src/lib/netlist/macro/nlm_ttl74xx.h",
159      MAME_DIR .. "src/lib/netlist/macro/nlm_cd4xxx.c",
160      MAME_DIR .. "src/lib/netlist/macro/nlm_cd4xxx.h",
161      MAME_DIR .. "src/lib/netlist/macro/nlm_opamp.c",
162      MAME_DIR .. "src/lib/netlist/macro/nlm_opamp.h",
163      MAME_DIR .. "src/lib/netlist/macro/nlm_other.c",
164      MAME_DIR .. "src/lib/netlist/macro/nlm_other.h",
165165}
trunk/scripts/src/tools.lua
r249194r249195
611611includedirs {
612612   MAME_DIR .. "src/osd",
613613   MAME_DIR .. "src/lib/util",
614   MAME_DIR .. "src/emu/netlist",
614   MAME_DIR .. "src/lib/netlist",
615615}
616616
617617files {
618   MAME_DIR .. "src/emu/netlist/prg/nltool.c",
618   MAME_DIR .. "src/lib/netlist/prg/nltool.c",
619619}
620620
621621--------------------------------------------------
r249194r249195
647647includedirs {
648648  MAME_DIR .. "src/osd",
649649  MAME_DIR .. "src/lib/util",
650  MAME_DIR .. "src/emu/netlist",
650  MAME_DIR .. "src/lib/netlist",
651651}
652652
653653files {
654  MAME_DIR .. "src/emu/netlist/prg/nlwav.c",
654  MAME_DIR .. "src/lib/netlist/prg/nlwav.c",
655655}
656656
657657--------------------------------------------------
trunk/scripts/target/mame/arcade.lua
r249194r249195
775775      MAME_DIR .. "src/mame",
776776      MAME_DIR .. "src/lib",
777777      MAME_DIR .. "src/lib/util",
778   MAME_DIR .. "src/emu/netlist",
778      MAME_DIR .. "src/lib/netlist",
779779      MAME_DIR .. "3rdparty",
780780      GEN_DIR  .. "mame/layout",
781781   }
trunk/scripts/target/mame/mess.lua
r249194r249195
886886      MAME_DIR .. "src/mame",
887887      MAME_DIR .. "src/lib",
888888      MAME_DIR .. "src/lib/util",
889   MAME_DIR .. "src/emu/netlist",
889      MAME_DIR .. "src/lib/netlist",
890890      MAME_DIR .. "3rdparty",
891891      GEN_DIR  .. "mess/layout",
892892      GEN_DIR  .. "mame/layout",
trunk/scripts/target/mame/nl.lua
r249194r249195
9292   includedirs {
9393      MAME_DIR .. "src/osd",
9494      MAME_DIR .. "src/emu",
95    MAME_DIR .. "src/emu/netlist",
95      MAME_DIR .. "src/lib/netlist",
9696      MAME_DIR .. "src/mame",
9797      MAME_DIR .. "src/lib",
9898      MAME_DIR .. "src/lib/util",
trunk/src/build/makedep.py
r249194r249195
151151               fullname = file_exists(root, name, folder,include_dirs)
152152               if fullname in files_included:
153153                   continue
154               if "src/emu/netlist/" in fullname:
154               if "src/lib/netlist/" in fullname:
155155                   continue
156156               if fullname!='':
157157                   if fullname in mappings.keys():
trunk/src/lib/netlist/analog/nld_bjt.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_bjt.c
5 *
6 */
7
8#include "solver/nld_solver.h"
9#include "analog/nld_bjt.h"
10#include "nl_setup.h"
11
12NETLIB_NAMESPACE_DEVICES_START()
13
14class diode
15{
16public:
17   diode() : m_Is(1e-15), m_VT(0.0258), m_VT_inv(1.0 / m_VT) {}
18   diode(const nl_double Is, const nl_double n)
19   {
20      m_Is = Is;
21      m_VT = 0.0258 * n;
22      m_VT_inv = 1.0 / m_VT;
23   }
24   void set(const nl_double Is, const nl_double n)
25   {
26      m_Is = Is;
27      m_VT = 0.0258 * n;
28      m_VT_inv = 1.0 / m_VT;
29   }
30   nl_double I(const nl_double V) const { return m_Is * nl_math::exp(V * m_VT_inv) - m_Is; }
31   nl_double g(const nl_double V) const { return m_Is * m_VT_inv * nl_math::exp(V * m_VT_inv); }
32   nl_double V(const nl_double I) const { return nl_math::e_log1p(I / m_Is) * m_VT; } // log1p(x)=log(1.0 + x)
33   nl_double gI(const nl_double I) const { return m_VT_inv * (I + m_Is); }
34
35private:
36   nl_double m_Is;
37   nl_double m_VT;
38   nl_double m_VT_inv;
39};
40
41
42
43// ----------------------------------------------------------------------------------------
44// nld_Q
45// ----------------------------------------------------------------------------------------
46
47NETLIB_NAME(Q)::NETLIB_NAME(Q)(const family_t afamily)
48: device_t(afamily)
49, m_qtype(BJT_NPN) { }
50
51NETLIB_NAME(Q)::~NETLIB_NAME(Q)()
52{
53}
54
55
56NETLIB_START(Q)
57{
58   register_param("MODEL", m_model, "");
59}
60
61NETLIB_RESET(Q)
62{
63}
64
65NETLIB_UPDATE(Q)
66{
67//    netlist().solver()->schedule1();
68}
69
70// ----------------------------------------------------------------------------------------
71// nld_QBJT_switch
72// ----------------------------------------------------------------------------------------
73
74NETLIB_START(QBJT_switch)
75{
76   NETLIB_NAME(Q)::start();
77
78   register_terminal("B", m_RB.m_P);
79   register_terminal("E", m_RB.m_N);
80   register_terminal("C", m_RC.m_P);
81   register_terminal("_E1", m_RC.m_N);
82
83   register_terminal("_B1", m_BC_dummy.m_P);
84   register_terminal("_C1", m_BC_dummy.m_N);
85
86   connect_late(m_RB.m_N, m_RC.m_N);
87
88   connect_late(m_RB.m_P, m_BC_dummy.m_P);
89   connect_late(m_RC.m_P, m_BC_dummy.m_N);
90
91   save(NLNAME(m_state_on));
92
93}
94
95NETLIB_RESET(QBJT_switch)
96{
97   NETLIB_NAME(Q)::reset();
98
99   m_state_on = 0;
100
101   m_RB.set(netlist().gmin(), 0.0, 0.0);
102   m_RC.set(netlist().gmin(), 0.0, 0.0);
103
104   m_BC_dummy.set(netlist().gmin() / 10.0, 0.0, 0.0);
105
106}
107
108NETLIB_UPDATE(QBJT_switch)
109{
110   if (!m_RB.m_P.net().isRailNet())
111      m_RB.m_P.schedule_solve();   // Basis
112   else if (!m_RB.m_N.net().isRailNet())
113      m_RB.m_N.schedule_solve();   // Emitter
114   else if (!m_RC.m_P.net().isRailNet())
115      m_RC.m_P.schedule_solve();   // Collector
116}
117
118
119NETLIB_UPDATE_PARAM(QBJT_switch)
120{
121   nl_double IS = m_model.model_value("IS");
122   nl_double BF = m_model.model_value("BF");
123   nl_double NF = m_model.model_value("NF");
124   //nl_double VJE = m_model.dValue("VJE", 0.75);
125
126   set_qtype((m_model.model_type() == "NPN") ? BJT_NPN : BJT_PNP);
127
128   nl_double alpha = BF / (1.0 + BF);
129
130   diode d(IS, NF);
131
132   // Assume 5mA Collector current for switch operation
133
134   m_V = d.V(0.005 / alpha);
135
136   /* Base current is 0.005 / beta
137    * as a rough estimate, we just scale the conductance down */
138
139   m_gB = 1.0 / (m_V/(0.005 / BF));
140
141   //m_gB = d.gI(0.005 / alpha);
142
143   if (m_gB < netlist().gmin())
144      m_gB = netlist().gmin();
145   m_gC =  d.gI(0.005); // very rough estimate
146}
147
148NETLIB_UPDATE_TERMINALS(QBJT_switch)
149{
150   const nl_double m = (is_qtype( BJT_NPN) ? 1 : -1);
151
152   const int new_state = (m_RB.deltaV() * m > m_V ) ? 1 : 0;
153   if (m_state_on ^ new_state)
154   {
155      const nl_double gb = new_state ? m_gB : netlist().gmin();
156      const nl_double gc = new_state ? m_gC : netlist().gmin();
157      const nl_double v  = new_state ? m_V * m : 0;
158
159      m_RB.set(gb, v,   0.0);
160      m_RC.set(gc, 0.0, 0.0);
161      //m_RB.update_dev();
162      //m_RC.update_dev();
163      m_state_on = new_state;
164   }
165}
166
167
168// ----------------------------------------------------------------------------------------
169// nld_Q - Ebers Moll
170// ----------------------------------------------------------------------------------------
171
172NETLIB_START(QBJT_EB)
173{
174   NETLIB_NAME(Q)::start();
175
176   register_terminal("E", m_D_EB.m_P);   // Cathode
177   register_terminal("B", m_D_EB.m_N);   // Anode
178
179   register_terminal("C", m_D_CB.m_P);   // Cathode
180   register_terminal("_B1", m_D_CB.m_N); // Anode
181
182   register_terminal("_E1", m_D_EC.m_P);
183   register_terminal("_C1", m_D_EC.m_N);
184
185   connect_late(m_D_EB.m_P, m_D_EC.m_P);
186   connect_late(m_D_EB.m_N, m_D_CB.m_N);
187   connect_late(m_D_CB.m_P, m_D_EC.m_N);
188
189   m_gD_BE.save("m_D_BE", *this);
190   m_gD_BC.save("m_D_BC", *this);
191
192}
193
194NETLIB_UPDATE(QBJT_EB)
195{
196   if (!m_D_EB.m_P.net().isRailNet())
197      m_D_EB.m_P.schedule_solve();   // Basis
198   else if (!m_D_EB.m_N.net().isRailNet())
199      m_D_EB.m_N.schedule_solve();   // Emitter
200   else
201      m_D_CB.m_N.schedule_solve();   // Collector
202}
203
204NETLIB_RESET(QBJT_EB)
205{
206   NETLIB_NAME(Q)::reset();
207}
208
209NETLIB_UPDATE_TERMINALS(QBJT_EB)
210{
211   const nl_double polarity = (qtype() == BJT_NPN ? 1.0 : -1.0);
212
213   m_gD_BE.update_diode(-m_D_EB.deltaV() * polarity);
214   m_gD_BC.update_diode(-m_D_CB.deltaV() * polarity);
215
216   const nl_double gee = m_gD_BE.G();
217   const nl_double gcc = m_gD_BC.G();
218   const nl_double gec =  m_alpha_r * gcc;
219   const nl_double gce =  m_alpha_f * gee;
220   const nl_double sIe = -m_gD_BE.I() + m_alpha_r * m_gD_BC.I();
221   const nl_double sIc = m_alpha_f * m_gD_BE.I() - m_gD_BC.I();
222   const nl_double Ie = (sIe + gee * m_gD_BE.Vd() - gec * m_gD_BC.Vd()) * polarity;
223   const nl_double Ic = (sIc - gce * m_gD_BE.Vd() + gcc * m_gD_BC.Vd()) * polarity;
224
225   m_D_EB.set_mat(gee, gec - gee, gce - gee, gee - gec, Ie, -Ie);
226   m_D_CB.set_mat(gcc, gce - gcc, gec - gcc, gcc - gce, Ic, -Ic);
227   m_D_EC.set_mat( 0,    -gec,      -gce,        0,       0,   0);
228}
229
230
231NETLIB_UPDATE_PARAM(QBJT_EB)
232{
233   nl_double IS = m_model.model_value("IS");
234   nl_double BF = m_model.model_value("BF");
235   nl_double NF = m_model.model_value("NF");
236   nl_double BR = m_model.model_value("BR");
237   nl_double NR = m_model.model_value("NR");
238   //nl_double VJE = m_model.dValue("VJE", 0.75);
239
240   set_qtype((m_model.model_type() == "NPN") ? BJT_NPN : BJT_PNP);
241
242   m_alpha_f = BF / (1.0 + BF);
243   m_alpha_r = BR / (1.0 + BR);
244
245   m_gD_BE.set_param(IS / m_alpha_f, NF, netlist().gmin());
246   m_gD_BC.set_param(IS / m_alpha_r, NR, netlist().gmin());
247}
248
249NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/analog/nld_bjt.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_bjt.h
5 *
6 */
7
8#ifndef NLD_BJT_H_
9#define NLD_BJT_H_
10
11#include "nl_base.h"
12#include "nld_twoterm.h"
13
14// -----------------------------------------------------------------------------
15// Macros
16// -----------------------------------------------------------------------------
17
18#define QBJT_SW(_name, _model)                                                 \
19      NET_REGISTER_DEV(QBJT_SW, _name)                                       \
20      NETDEV_PARAMI(_name,  MODEL,   _model)
21
22#define QBJT_EB(_name, _model)                                                 \
23      NET_REGISTER_DEV(QBJT_EB, _name)                                       \
24      NETDEV_PARAMI(_name,  MODEL,   _model)
25
26
27NETLIB_NAMESPACE_DEVICES_START()
28
29// -----------------------------------------------------------------------------
30// nld_Q - Base classes
31// -----------------------------------------------------------------------------
32
33// Have a common start for transistors
34
35class NETLIB_NAME(Q) : public device_t
36{
37public:
38   enum q_type {
39      BJT_NPN,
40      BJT_PNP
41   };
42
43   NETLIB_NAME(Q)(const family_t afamily);
44   virtual ~NETLIB_NAME(Q)();
45
46   inline q_type qtype() const { return m_qtype; }
47   inline bool is_qtype(q_type atype) const { return m_qtype == atype; }
48   inline void set_qtype(q_type atype) { m_qtype = atype; }
49protected:
50   virtual void start();
51   virtual void reset();
52   ATTR_HOT void update();
53
54   param_model_t m_model;
55private:
56   q_type m_qtype;
57};
58
59class NETLIB_NAME(QBJT) : public NETLIB_NAME(Q)
60{
61public:
62
63   NETLIB_NAME(QBJT)(const family_t afamily)
64   : NETLIB_NAME(Q)(afamily) { }
65
66   virtual ~NETLIB_NAME(QBJT)() { }
67
68protected:
69
70private:
71};
72
73
74
75
76// -----------------------------------------------------------------------------
77// nld_QBJT_switch
78// -----------------------------------------------------------------------------
79
80
81/*
82 *         + -              C
83 *   B ----VVV----+         |
84 *                |         |
85 *                Rb        Rc
86 *                Rb        Rc
87 *                Rb        Rc
88 *                |         |
89 *                +----+----+
90 *                     |
91 *                     E
92 */
93
94class NETLIB_NAME(QBJT_switch) : public NETLIB_NAME(QBJT)
95{
96public:
97   ATTR_COLD NETLIB_NAME(QBJT_switch)()
98   : NETLIB_NAME(QBJT)(BJT_SWITCH),
99      m_RB(object_t::ANALOG),
100      m_RC(object_t::ANALOG),
101      m_BC_dummy(object_t::ANALOG),
102      m_gB(NETLIST_GMIN_DEFAULT), m_gC(NETLIST_GMIN_DEFAULT), m_V(0.0), m_state_on(0) { }
103
104
105   ATTR_HOT void virtual update();
106
107   nld_twoterm m_RB;
108   nld_twoterm m_RC;
109
110   // FIXME: this is needed so we have all terminals belong to one net list
111
112   nld_twoterm m_BC_dummy;
113
114protected:
115
116   virtual void start();
117   ATTR_HOT virtual void update_param();
118   virtual void reset();
119   NETLIB_UPDATE_TERMINALSI();
120
121   nl_double m_gB; // base conductance / switch on
122   nl_double m_gC; // collector conductance / switch on
123   nl_double m_V; // internal voltage source
124   UINT8 m_state_on;
125
126private:
127};
128
129// -----------------------------------------------------------------------------
130// nld_QBJT_EB
131// -----------------------------------------------------------------------------
132
133
134class NETLIB_NAME(QBJT_EB) : public NETLIB_NAME(QBJT)
135{
136public:
137   ATTR_COLD NETLIB_NAME(QBJT_EB)()
138   : NETLIB_NAME(QBJT)(BJT_EB),
139      m_D_CB(object_t::ANALOG),
140      m_D_EB(object_t::ANALOG),
141      m_D_EC(object_t::ANALOG),
142      m_alpha_f(0),
143      m_alpha_r(0)
144      { }
145
146protected:
147
148   virtual void start();
149   virtual void reset();
150   ATTR_HOT void update_param();
151   ATTR_HOT void virtual update();
152   NETLIB_UPDATE_TERMINALSI();
153
154   generic_diode m_gD_BC;
155   generic_diode m_gD_BE;
156
157   nld_twoterm m_D_CB;  // gcc, gce - gcc, gec - gcc, gcc - gce | Ic
158   nld_twoterm m_D_EB;  // gee, gec - gee, gce - gee, gee - gec | Ie
159   nld_twoterm m_D_EC;  // 0, -gec, -gcc, 0 | 0
160
161   nl_double m_alpha_f;
162   nl_double m_alpha_r;
163
164private:
165};
166
167NETLIB_NAMESPACE_DEVICES_END()
168
169#endif /* NLD_BJT_H_ */
trunk/src/lib/netlist/analog/nld_fourterm.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_fourterm.c
5 *
6 */
7
8#include "solver/nld_solver.h"
9#include "nld_fourterm.h"
10#include "nl_setup.h"
11
12NETLIB_NAMESPACE_DEVICES_START()
13
14// ----------------------------------------------------------------------------------------
15// nld_VCCS
16// ----------------------------------------------------------------------------------------
17
18NETLIB_START(VCCS)
19{
20   start_internal(NL_FCONST(1.0) / netlist().gmin());
21   m_gfac = NL_FCONST(1.0);
22}
23
24void NETLIB_NAME(VCCS)::start_internal(const nl_double def_RI)
25{
26   register_param("G", m_G, 1.0);
27   register_param("RI", m_RI, def_RI);
28
29   register_terminal("IP", m_IP);
30   register_terminal("IN", m_IN);
31   register_terminal("OP", m_OP);
32   register_terminal("ON", m_ON);
33
34   register_terminal("_OP1", m_OP1);
35   register_terminal("_ON1", m_ON1);
36
37   m_IP.m_otherterm = &m_IN; // <= this should be NULL and terminal be filtered out prior to solving...
38   m_IN.m_otherterm = &m_IP; // <= this should be NULL and terminal be filtered out prior to solving...
39
40   m_OP.m_otherterm = &m_IP;
41   m_OP1.m_otherterm = &m_IN;
42
43   m_ON.m_otherterm = &m_IP;
44   m_ON1.m_otherterm = &m_IN;
45
46   connect_late(m_OP, m_OP1);
47   connect_late(m_ON, m_ON1);
48}
49
50NETLIB_RESET(VCCS)
51{
52   const nl_double m_mult = m_G.Value() * m_gfac; // 1.0 ==> 1V ==> 1A
53   const nl_double GI = NL_FCONST(1.0) / m_RI.Value();
54
55   m_IP.set(GI);
56   m_IN.set(GI);
57
58   m_OP.set(m_mult, NL_FCONST(0.0));
59   m_OP1.set(-m_mult, NL_FCONST(0.0));
60
61   m_ON.set(-m_mult, NL_FCONST(0.0));
62   m_ON1.set(m_mult, NL_FCONST(0.0));
63}
64
65NETLIB_UPDATE_PARAM(VCCS)
66{
67   NETLIB_NAME(VCCS)::reset();
68}
69
70NETLIB_UPDATE(VCCS)
71{
72   /* only called if connected to a rail net ==> notify the solver to recalculate */
73   if (!m_IP.net().isRailNet())
74      m_IP.schedule_solve();
75   else if (!m_IN.net().isRailNet())
76      m_IN.schedule_solve();
77   else if (!m_OP.net().isRailNet())
78      m_OP.schedule_solve();
79   else if (!m_ON.net().isRailNet())
80      m_ON.schedule_solve();
81}
82
83// ----------------------------------------------------------------------------------------
84// nld_LVCCS
85// ----------------------------------------------------------------------------------------
86
87NETLIB_START(LVCCS)
88{
89   NETLIB_NAME(VCCS)::start();
90   register_param("CURLIM", m_cur_limit, 1000.0);
91}
92
93NETLIB_RESET(LVCCS)
94{
95   NETLIB_NAME(VCCS)::reset();
96}
97
98NETLIB_UPDATE_PARAM(LVCCS)
99{
100   NETLIB_NAME(VCCS)::update_param();
101}
102
103NETLIB_UPDATE(LVCCS)
104{
105   NETLIB_NAME(VCCS)::update();
106}
107
108NETLIB_UPDATE_TERMINALS(LVCCS)
109{
110   const nl_double m_mult = m_G.Value() * m_gfac; // 1.0 ==> 1V ==> 1A
111   const nl_double vi = m_IP.net().m_cur_Analog - m_IN.net().m_cur_Analog;
112
113   if (std::abs(m_mult / m_cur_limit * vi) > 0.5)
114      m_vi = m_vi + 0.2*std::tanh((vi - m_vi)/0.2);
115   else
116      m_vi = vi;
117
118   const nl_double x = m_mult / m_cur_limit * m_vi;
119   const nl_double X = std::tanh(x);
120
121   const nl_double beta = m_mult * (1.0 - X*X);
122   const nl_double I = m_cur_limit * X - beta * m_vi;
123
124   m_OP.set(beta, NL_FCONST(0.0), I);
125   m_OP1.set(-beta, NL_FCONST(0.0));
126
127   m_ON.set(-beta, NL_FCONST(0.0), -I);
128   m_ON1.set(beta, NL_FCONST(0.0));
129}
130
131// ----------------------------------------------------------------------------------------
132// nld_CCCS
133// ----------------------------------------------------------------------------------------
134
135NETLIB_START(CCCS)
136{
137   start_internal(1.0);
138   m_gfac = NL_FCONST(1.0) / m_RI.Value();
139}
140
141NETLIB_RESET(CCCS)
142{
143   NETLIB_NAME(VCCS)::reset();
144}
145
146NETLIB_UPDATE_PARAM(CCCS)
147{
148   NETLIB_NAME(VCCS)::update_param();
149}
150
151NETLIB_UPDATE(CCCS)
152{
153   NETLIB_NAME(VCCS)::update();
154}
155
156// ----------------------------------------------------------------------------------------
157// nld_VCVS
158// ----------------------------------------------------------------------------------------
159
160NETLIB_START(VCVS)
161{
162   NETLIB_NAME(VCCS)::start();
163
164   register_param("RO", m_RO, 1.0);
165
166   register_terminal("_OP2", m_OP2);
167   register_terminal("_ON2", m_ON2);
168
169   m_OP2.m_otherterm = &m_ON2;
170   m_ON2.m_otherterm = &m_OP2;
171
172   connect_late(m_OP2, m_OP1);
173   connect_late(m_ON2, m_ON1);
174}
175
176NETLIB_RESET(VCVS)
177{
178   m_gfac = NL_FCONST(1.0) / m_RO.Value();
179   NETLIB_NAME(VCCS)::reset();
180
181   m_OP2.set(NL_FCONST(1.0) / m_RO.Value());
182   m_ON2.set(NL_FCONST(1.0) / m_RO.Value());
183}
184
185NETLIB_UPDATE_PARAM(VCVS)
186{
187}
188
189NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/analog/nld_fourterm.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_fourterm.h
5 *
6 */
7
8#ifndef NLD_FOURTERM_H_
9#define NLD_FOURTERM_H_
10
11
12#include "nl_base.h"
13#include "nld_twoterm.h"
14
15// ----------------------------------------------------------------------------------------
16// Macros
17// ----------------------------------------------------------------------------------------
18
19#define VCCS(_name)                                                            \
20      NET_REGISTER_DEV(VCCS, _name)
21
22#define CCCS(_name)                                                            \
23      NET_REGISTER_DEV(CCCS, _name)
24
25#define VCVS(_name)                                                            \
26      NET_REGISTER_DEV(VCVS, _name)
27
28#define LVCCS(_name)                                                           \
29      NET_REGISTER_DEV(LVCCS, _name)
30
31NETLIB_NAMESPACE_DEVICES_START()
32
33// ----------------------------------------------------------------------------------------
34// nld_VCCS
35// ----------------------------------------------------------------------------------------
36
37/*
38 *   Voltage controlled current source
39 *
40 *   IP ---+           +------> OP
41 *         |           |
42 *         RI          I
43 *         RI => G =>  I    IOut = (V(IP)-V(IN)) * G
44 *         RI          I
45 *         |           |
46 *   IN ---+           +------< ON
47 *
48 *   G=1 ==> 1V ==> 1A
49 *
50 *   RI = 1 / NETLIST_GMIN
51 *
52 */
53
54class NETLIB_NAME(VCCS) : public device_t
55{
56public:
57   ATTR_COLD NETLIB_NAME(VCCS)()
58   : device_t(VCCS), m_gfac(1.0) {  }
59   ATTR_COLD NETLIB_NAME(VCCS)(const family_t afamily)
60   : device_t(afamily), m_gfac(1.0) {  }
61
62   param_double_t m_G;
63   param_double_t m_RI;
64
65protected:
66   virtual void start();
67   virtual void reset();
68   virtual void update_param();
69   ATTR_HOT virtual void update();
70
71   ATTR_COLD void start_internal(const nl_double def_RI);
72
73   terminal_t m_OP;
74   terminal_t m_ON;
75
76   terminal_t m_IP;
77   terminal_t m_IN;
78
79   terminal_t m_OP1;
80   terminal_t m_ON1;
81
82   nl_double m_gfac;
83};
84
85/* Limited Current source*/
86
87class NETLIB_NAME(LVCCS) : public NETLIB_NAME(VCCS)
88{
89public:
90   ATTR_COLD NETLIB_NAME(LVCCS)()
91   : NETLIB_NAME(VCCS)(LVCCS), m_vi(0.0) {  }
92   ATTR_COLD NETLIB_NAME(LVCCS)(const family_t afamily)
93   : NETLIB_NAME(VCCS)(afamily), m_vi(0.0) {  }
94
95   param_double_t m_cur_limit; /* current limit */
96
97protected:
98   virtual void start();
99   virtual void reset();
100   virtual void update_param();
101   ATTR_HOT virtual void update();
102   NETLIB_UPDATE_TERMINALSI();
103
104   nl_double m_vi;
105};
106
107// ----------------------------------------------------------------------------------------
108// nld_CCCS
109// ----------------------------------------------------------------------------------------
110
111/*
112 *   Current controlled current source
113 *
114 *   IP ---+           +------> OP
115 *         |           |
116 *         RI          I
117 *         RI => G =>  I    IOut = (V(IP)-V(IN)) / RI  * G
118 *         RI          I
119 *         |           |
120 *   IN ---+           +------< ON
121 *
122 *   G=1 ==> 1A ==> 1A
123 *
124 *   RI = 1
125 *
126 *   This needs high levels of accuracy to work with 1 Ohm RI.
127 *
128 */
129
130class NETLIB_NAME(CCCS) : public NETLIB_NAME(VCCS)
131{
132public:
133   ATTR_COLD NETLIB_NAME(CCCS)()
134   : NETLIB_NAME(VCCS)(CCCS), m_gfac(1.0) {  }
135
136protected:
137   virtual void start();
138   virtual void reset();
139   virtual void update_param();
140   ATTR_HOT void update();
141
142   nl_double m_gfac;
143};
144
145
146// ----------------------------------------------------------------------------------------
147// nld_VCVS
148// ----------------------------------------------------------------------------------------
149
150/*
151 *   Voltage controlled voltage source
152 *
153 *   Parameters:
154 *     G        Default: 1
155 *     RO       Default: 1  (would be typically 50 for an op-amp
156 *
157 *   IP ---+           +--+---- OP
158 *         |           |  |
159 *         RI          I  RO
160 *         RI => G =>  I  RO              V(OP) - V(ON) = (V(IP)-V(IN)) * G
161 *         RI          I  RO
162 *         |           |  |
163 *   IN ---+           +--+---- ON
164 *
165 *   G=1 ==> 1V ==> 1V
166 *
167 *   RI = 1 / NETLIST_GMIN
168 *
169 *   Internal GI = G / RO
170 *
171 */
172
173
174class NETLIB_NAME(VCVS) : public NETLIB_NAME(VCCS)
175{
176public:
177   ATTR_COLD NETLIB_NAME(VCVS)()
178   : NETLIB_NAME(VCCS)(VCVS) { }
179
180   param_double_t m_RO;
181
182protected:
183   virtual void start();
184   virtual void reset();
185   virtual void update_param();
186   //ATTR_HOT void update();
187
188   terminal_t m_OP2;
189   terminal_t m_ON2;
190
191};
192
193NETLIB_NAMESPACE_DEVICES_END()
194
195
196#endif /* NLD_FOURTERM_H_ */
trunk/src/lib/netlist/analog/nld_opamps.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_opamps.c
5 *
6 */
7
8#include "nld_opamps.h"
9#include "devices/net_lib.h"
10
11NETLIST_START(opamp_lm3900)
12
13   /*
14    *  Fast norton opamp model without bandwidth
15    */
16
17   /* Terminal definitions for calling netlists */
18
19   ALIAS(PLUS, R1.1) // Positive input
20   ALIAS(MINUS, R2.1) // Negative input
21   ALIAS(OUT, G1.OP) // Opamp output ...
22   ALIAS(VM, G1.ON)  // V- terminal
23   ALIAS(VP, DUMMY.I)  // V+ terminal
24
25   DUMMY_INPUT(DUMMY)
26
27   /* The opamp model */
28
29   RES(R1, 1)
30   RES(R2, 1)
31   NET_C(R1.1, G1.IP)
32   NET_C(R2.1, G1.IN)
33   NET_C(R1.2, R2.2, G1.ON)
34   VCVS(G1)
35   PARAM(G1.G, 10000000)
36   //PARAM(G1.RI, 1)
37   PARAM(G1.RO, RES_K(8))
38
39NETLIST_END()
40
41NETLIB_NAMESPACE_DEVICES_START()
42
43/*
44 * Type = 0: Impedance changer
45 *        1; Idealized opamp
46 *        2; opamp with first pole
47 *        3: opamp with first pole + output limit
48 *        4: opamp with input stage, first pole + output limit
49 */
50
51NETLIB_START(OPAMP)
52{
53   register_param("MODEL", m_model, "");
54
55   m_type = m_model.model_value("TYPE");
56
57   register_input("VCC", m_VCC);
58   register_input("GND", m_GND);
59
60   register_output("VL", m_VL);
61   register_output("VH", m_VH);
62   register_output("VREF", m_VREF);
63
64   register_sub("G1", m_G1);
65   register_sub("RP1", m_RP);
66
67   if (m_type == 1)
68   {
69      register_subalias("PLUS", "G1.IP");
70      register_subalias("MINUS", "G1.IN");
71      register_subalias("OUT", "G1.OP");
72
73      connect_late("G1.ON", "VREF");
74      connect_late("RP1.2", "VREF");
75      connect_late("RP1.1", "G1.OP");
76
77   }
78   else if (m_type == 3)
79   {
80      register_sub("CP1", m_CP);
81      register_sub("EBUF", m_EBUF);
82      register_sub("DN", m_DN);
83      register_sub("DP", m_DP);
84
85      register_subalias("PLUS", "G1.IP");
86      register_subalias("MINUS", "G1.IN");
87      register_subalias("OUT", "EBUF.OP");
88
89      connect_late("EBUF.ON", "VREF");
90
91      connect_late("G1.ON", "VREF");
92      connect_late("RP1.2", "VREF");
93      connect_late("CP1.2", "VREF");
94      connect_late("EBUF.IN", "VREF");
95
96      connect_late("RP1.1", "G1.OP");
97      connect_late("CP1.1", "RP1.1");
98
99      connect_late("DP.K", "VH");
100      connect_late("VL", "DN.A");
101      connect_late("DP.A", "DN.K");
102      connect_late("DN.K", "RP1.1");
103      connect_late("EBUF.IP", "RP1.1");
104   }
105   else
106      netlist().log().fatal("Unknown opamp type: {1}", m_type);
107}
108
109/* .model abc OPAMP(VLH=2.0 VLL=0.2 FPF=5 UGF=10k SLEW=0.6u RI=1000k RO=50 DAB=0.002)
110 *
111 * Differential Amp Bias ~ op amp's total quiescent current.
112 * */
113
114NETLIB_UPDATE(OPAMP)
115{
116   const double cVt = 0.0258 * 1.0; // * m_n;
117   const double cId = m_model.model_value("DAB"); // 3 mA
118   const double cVd = cVt * nl_math::log(cId / 1e-15 + 1.0);
119   m_VH.set_Q(INPANALOG(m_VCC) - m_model.model_value("VLH") - cVd);
120   m_VL.set_Q(INPANALOG(m_GND) + m_model.model_value("VLL") + cVd);
121   m_VREF.set_Q((INPANALOG(m_VCC) + INPANALOG(m_GND)) / 2.0);
122}
123
124NETLIB_RESET(OPAMP)
125{
126   m_G1.do_reset();
127   m_G1.m_RI.setTo(m_model.model_value("RI"));
128
129   if (m_type == 1)
130   {
131      double RO = m_model.model_value("RO");
132      double G = m_model.model_value("UGF") / m_model.model_value("FPF") / RO;
133      m_RP.set_R(RO);
134      m_G1.m_G.setTo(G);
135   }
136   else if (m_type == 3)
137   {
138      m_EBUF.do_reset();
139      m_DP.do_reset();
140      m_DN.do_reset();
141      m_CP.do_reset();
142      m_RP.do_reset();
143
144      m_EBUF.m_G.setTo(1.0);
145      m_EBUF.m_RO.setTo(m_model.model_value("RO"));
146      m_DP.m_model.setTo("D(IS=1e-15 N=1)");
147      m_DN.m_model.setTo("D(IS=1e-15 N=1)");
148
149      double CP = m_model.model_value("DAB") / m_model.model_value("SLEW");
150      double RP = 0.5 / 3.1459 / CP / m_model.model_value("FPF");
151      double G = m_model.model_value("UGF") / m_model.model_value("FPF") / RP;
152
153      m_CP.m_C.setTo(CP);
154      m_RP.set_R(RP);
155      m_G1.m_G.setTo(G);
156
157   }
158
159
160}
161
162NETLIB_UPDATE_PARAM(OPAMP)
163{
164}
165
166/*
167NETLIB_DEVICE_WITH_PARAMS(OPAMPx,
168    NETLIB_NAME(R) m_RP;
169    NETLIB_NAME(C) m_CP;
170    NETLIB_NAME(VCCS) m_G1;
171    NETLIB_NAME(VCVS) m_EBUF;
172
173    param_model_t m_model;
174    analog_input_t m_VH;
175    analog_input_t m_VL;
176    analog_input_t m_VREF;
177);
178*/
179
180NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/analog/nld_opamps.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_opamps.h
5 *
6 */
7
8//#pragma once
9
10#ifndef NLD_OPAMPS_H_
11#define NLD_OPAMPS_H_
12
13#include "nl_base.h"
14#include "nl_setup.h"
15#include "nld_twoterm.h"
16#include "nld_fourterm.h"
17
18// ----------------------------------------------------------------------------------------
19// Macros
20// ----------------------------------------------------------------------------------------
21
22#define OPAMP(_name, _model)                                                   \
23      NET_REGISTER_DEV(OPAMP, _name)                                         \
24      NETDEV_PARAMI(_name, MODEL, _model)
25
26#define LM3900(_name)                                                          \
27   SUBMODEL(opamp_lm3900, _name)
28
29// ----------------------------------------------------------------------------------------
30// Devices ...
31// ----------------------------------------------------------------------------------------
32
33NETLIST_EXTERNAL(opamp_lm3900)
34
35NETLIB_NAMESPACE_DEVICES_START()
36
37NETLIB_DEVICE_WITH_PARAMS(OPAMP,
38   NETLIB_NAME(R) m_RP;
39   NETLIB_NAME(C) m_CP;
40   NETLIB_NAME(VCCS) m_G1;
41   NETLIB_NAME(VCVS) m_EBUF;
42   NETLIB_NAME(D) m_DP;
43   NETLIB_NAME(D) m_DN;
44
45   analog_input_t m_VCC;
46   analog_input_t m_GND;
47
48   param_model_t m_model;
49   analog_output_t m_VH;
50   analog_output_t m_VL;
51   analog_output_t m_VREF;
52
53   /* state */
54   unsigned m_type;
55);
56
57NETLIB_NAMESPACE_DEVICES_END()
58
59#endif /* NLD_OPAMPS_H_ */
trunk/src/lib/netlist/analog/nld_switches.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_legacy.c
5 *
6 */
7
8#include "nld_switches.h"
9#include "nl_setup.h"
10
11#define R_OFF   (1.0 / netlist().gmin())
12#define R_ON    0.01
13
14NETLIB_NAMESPACE_DEVICES_START()
15
16// ----------------------------------------------------------------------------------------
17// SWITCH
18// ----------------------------------------------------------------------------------------
19
20NETLIB_START(switch1)
21{
22   register_sub("R", m_R);
23
24   register_param("POS", m_POS, 0);
25
26   register_subalias("1", m_R.m_P);
27   register_subalias("2", m_R.m_N);
28}
29
30NETLIB_RESET(switch1)
31{
32   m_R.do_reset();
33
34   m_R.set_R(R_OFF);
35}
36
37NETLIB_UPDATE(switch1)
38{
39   if (m_POS.Value() == 0)
40   {
41      m_R.set_R(R_OFF);
42   }
43   else
44   {
45      m_R.set_R(R_ON);
46   }
47
48   m_R.update_dev();
49}
50
51NETLIB_UPDATE_PARAM(switch1)
52{
53   update();
54}
55
56// ----------------------------------------------------------------------------------------
57// SWITCH2
58// ----------------------------------------------------------------------------------------
59
60
61NETLIB_START(switch2)
62{
63   register_sub("R1", m_R[0]);
64   register_sub("R2", m_R[1]);
65
66   register_param("POS", m_POS, 0);
67
68   connect_late(m_R[0].m_N, m_R[1].m_N);
69
70   register_subalias("1", m_R[0].m_P);
71   register_subalias("2", m_R[1].m_P);
72
73   register_subalias("Q", m_R[0].m_N);
74}
75
76NETLIB_RESET(switch2)
77{
78   m_R[0].do_reset();
79   m_R[1].do_reset();
80
81   m_R[0].set_R(R_ON);
82   m_R[1].set_R(R_OFF);
83}
84
85NETLIB_UPDATE(switch2)
86{
87   if (m_POS.Value() == 0)
88   {
89      m_R[0].set_R(R_ON);
90      m_R[1].set_R(R_OFF);
91   }
92   else
93   {
94      m_R[0].set_R(R_OFF);
95      m_R[1].set_R(R_ON);
96   }
97
98   m_R[0].update_dev();
99   m_R[1].update_dev();
100}
101
102NETLIB_UPDATE_PARAM(switch2)
103{
104   update();
105}
106
107NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/analog/nld_switches.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_switches.h
5 *
6 */
7
8#pragma once
9
10#ifndef NLD_SWITCHES_H_
11#define NLD_SWITCHES_H_
12
13#include "nl_base.h"
14#include "nld_twoterm.h"
15
16// ----------------------------------------------------------------------------------------
17// Macros
18// ----------------------------------------------------------------------------------------
19
20#define SWITCH(_name)                                                              \
21      NET_REGISTER_DEV(SWITCH, _name)
22
23#define SWITCH2(_name)                                                              \
24      NET_REGISTER_DEV(SWITCH2, _name)
25
26// ----------------------------------------------------------------------------------------
27// Devices ...
28// ----------------------------------------------------------------------------------------
29
30NETLIB_NAMESPACE_DEVICES_START()
31
32NETLIB_DEVICE_WITH_PARAMS(switch1,
33   NETLIB_NAME(R_base) m_R;
34
35   param_int_t m_POS;
36);
37
38NETLIB_DEVICE_WITH_PARAMS(switch2,
39   NETLIB_NAME(R_base) m_R[2];
40
41   param_int_t m_POS;
42);
43
44NETLIB_NAMESPACE_DEVICES_END()
45
46#endif /* NLD_SWITCHES_H_ */
trunk/src/lib/netlist/analog/nld_twoterm.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_twoterm.c
5 *
6 */
7
8#include <solver/nld_solver.h>
9#include <algorithm>
10
11#include "nld_twoterm.h"
12
13NETLIB_NAMESPACE_DEVICES_START()
14
15// ----------------------------------------------------------------------------------------
16// generic_diode
17// ----------------------------------------------------------------------------------------
18
19ATTR_COLD generic_diode::generic_diode()
20{
21   m_Vd = 0.7;
22   set_param(1e-15, 1, 1e-15);
23}
24
25ATTR_COLD void generic_diode::set_param(const nl_double Is, const nl_double n, nl_double gmin)
26{
27   static const double csqrt2 = nl_math::sqrt(2.0);
28   m_Is = Is;
29   m_n = n;
30   m_gmin = gmin;
31
32   m_Vt = 0.0258 * m_n;
33
34   m_Vcrit = m_Vt * nl_math::log(m_Vt / m_Is / csqrt2);
35   m_VtInv = 1.0 / m_Vt;
36}
37
38ATTR_COLD void generic_diode::save(pstring name, object_t &parent)
39{
40   parent.save(m_Vd, name + ".m_Vd");
41   parent.save(m_Id, name + ".m_Id");
42   parent.save(m_G, name + ".m_G");
43}
44
45// ----------------------------------------------------------------------------------------
46// nld_twoterm
47// ----------------------------------------------------------------------------------------
48
49ATTR_COLD NETLIB_NAME(twoterm)::NETLIB_NAME(twoterm)(const family_t afamily)
50      : device_t(afamily)
51{
52   m_P.m_otherterm = &m_N;
53   m_N.m_otherterm = &m_P;
54}
55
56ATTR_COLD NETLIB_NAME(twoterm)::NETLIB_NAME(twoterm)()
57      : device_t(TWOTERM)
58{
59   m_P.m_otherterm = &m_N;
60   m_N.m_otherterm = &m_P;
61}
62
63NETLIB_START(twoterm)
64{
65}
66
67NETLIB_RESET(twoterm)
68{
69}
70
71
72NETLIB_UPDATE(twoterm)
73{
74   /* only called if connected to a rail net ==> notify the solver to recalculate */
75   /* we only need to call the non-rail terminal */
76   if (!m_P.net().isRailNet())
77      m_P.schedule_solve();
78   else
79      m_N.schedule_solve();
80}
81
82// ----------------------------------------------------------------------------------------
83// nld_R
84// ----------------------------------------------------------------------------------------
85
86NETLIB_START(R_base)
87{
88   NETLIB_NAME(twoterm)::start();
89   register_terminal("1", m_P);
90   register_terminal("2", m_N);
91}
92
93NETLIB_RESET(R_base)
94{
95   NETLIB_NAME(twoterm)::reset();
96   set_R(1.0 / netlist().gmin());
97}
98
99NETLIB_UPDATE(R_base)
100{
101   NETLIB_NAME(twoterm)::update();
102}
103
104NETLIB_START(R)
105{
106   NETLIB_NAME(R_base)::start();
107   register_param("R", m_R, 1.0 / netlist().gmin());
108}
109
110NETLIB_RESET(R)
111{
112   NETLIB_NAME(R_base)::reset();
113}
114
115NETLIB_UPDATE(R)
116{
117   NETLIB_NAME(twoterm)::update();
118}
119
120NETLIB_UPDATE_PARAM(R)
121{
122   update_dev();
123   if (m_R.Value() > 1e-9)
124      set_R(m_R.Value());
125   else
126      set_R(1e-9);
127}
128
129// ----------------------------------------------------------------------------------------
130// nld_POT
131// ----------------------------------------------------------------------------------------
132
133NETLIB_START(POT)
134{
135   register_sub("R1", m_R1);
136   register_sub("R2", m_R2);
137
138   register_subalias("1", m_R1.m_P);
139   register_subalias("2", m_R1.m_N);
140   register_subalias("3", m_R2.m_N);
141
142   connect_late(m_R2.m_P, m_R1.m_N);
143
144   register_param("R", m_R, 1.0 / netlist().gmin());
145   register_param("DIAL", m_Dial, 0.5);
146   register_param("DIALLOG", m_DialIsLog, 0);
147
148}
149
150NETLIB_RESET(POT)
151{
152   m_R1.do_reset();
153   m_R2.do_reset();
154}
155
156NETLIB_UPDATE(POT)
157{
158   m_R1.update_dev();
159   m_R2.update_dev();
160}
161
162NETLIB_UPDATE_PARAM(POT)
163{
164   nl_double v = m_Dial.Value();
165   if (m_DialIsLog.Value())
166      v = (nl_math::exp(v) - 1.0) / (nl_math::exp(1.0) - 1.0);
167
168   m_R1.update_dev();
169   m_R2.update_dev();
170
171   m_R1.set_R(std::max(m_R.Value() * v, netlist().gmin()));
172   m_R2.set_R(std::max(m_R.Value() * (NL_FCONST(1.0) - v), netlist().gmin()));
173
174}
175
176// ----------------------------------------------------------------------------------------
177// nld_POT2
178// ----------------------------------------------------------------------------------------
179
180NETLIB_START(POT2)
181{
182   register_sub("R1", m_R1);
183
184   register_subalias("1", m_R1.m_P);
185   register_subalias("2", m_R1.m_N);
186
187   register_param("R", m_R, 1.0 / netlist().gmin());
188   register_param("DIAL", m_Dial, 0.5);
189   register_param("REVERSE", m_Reverse, 0);
190   register_param("DIALLOG", m_DialIsLog, 0);
191
192}
193
194NETLIB_RESET(POT2)
195{
196   m_R1.do_reset();
197}
198
199NETLIB_UPDATE(POT2)
200{
201   m_R1.update_dev();
202}
203
204NETLIB_UPDATE_PARAM(POT2)
205{
206   nl_double v = m_Dial.Value();
207
208   if (m_DialIsLog.Value())
209      v = (nl_math::exp(v) - 1.0) / (nl_math::exp(1.0) - 1.0);
210   if (m_Reverse.Value())
211      v = 1.0 - v;
212
213   m_R1.update_dev();
214
215   m_R1.set_R(std::max(m_R.Value() * v, netlist().gmin()));
216}
217
218// ----------------------------------------------------------------------------------------
219// nld_C
220// ----------------------------------------------------------------------------------------
221
222NETLIB_START(C)
223{
224   register_terminal("1", m_P);
225   register_terminal("2", m_N);
226
227   register_param("C", m_C, 1e-6);
228
229   // set up the element
230   //set(netlist().gmin(), 0.0, -5.0 / netlist().gmin());
231   //set(1.0/NETLIST_GMIN, 0.0, -5.0 * NETLIST_GMIN);
232}
233
234NETLIB_RESET(C)
235{
236   set(netlist().gmin(), 0.0, -5.0 / netlist().gmin());
237   //set(1.0/NETLIST_GMIN, 0.0, -5.0 * NETLIST_GMIN);
238}
239
240NETLIB_UPDATE_PARAM(C)
241{
242   //step_time(1.0/48000.0);
243   m_GParallel = netlist().gmin() * m_C.Value();
244}
245
246NETLIB_UPDATE(C)
247{
248   NETLIB_NAME(twoterm)::update();
249}
250
251ATTR_HOT void NETLIB_NAME(C)::step_time(const nl_double st)
252{
253   /* Gpar should support convergence */
254   const nl_double G = m_C.Value() / st +  m_GParallel;
255   const nl_double I = -G * deltaV();
256   set(G, 0.0, I);
257}
258
259// ----------------------------------------------------------------------------------------
260// nld_D
261// ----------------------------------------------------------------------------------------
262
263NETLIB_START(D)
264{
265   register_terminal("A", m_P);
266   register_terminal("K", m_N);
267   register_param("MODEL", m_model, "");
268
269   m_D.save("m_D", *this);
270
271}
272
273
274NETLIB_UPDATE_PARAM(D)
275{
276   nl_double Is = m_model.model_value("IS");
277   nl_double n = m_model.model_value("N");
278
279   m_D.set_param(Is, n, netlist().gmin());
280}
281
282NETLIB_UPDATE(D)
283{
284   NETLIB_NAME(twoterm)::update();
285}
286
287NETLIB_UPDATE_TERMINALS(D)
288{
289   m_D.update_diode(deltaV());
290   set(m_D.G(), 0.0, m_D.Ieq());
291}
292
293// ----------------------------------------------------------------------------------------
294// nld_VS
295// ----------------------------------------------------------------------------------------
296
297NETLIB_START(VS)
298{
299   NETLIB_NAME(twoterm)::start();
300
301   register_param("R", m_R, 0.1);
302   register_param("V", m_V, 0.0);
303
304   register_terminal("P", m_P);
305   register_terminal("N", m_N);
306}
307
308NETLIB_RESET(VS)
309{
310   NETLIB_NAME(twoterm)::reset();
311   this->set(1.0 / m_R, m_V, 0.0);
312}
313
314NETLIB_UPDATE(VS)
315{
316   NETLIB_NAME(twoterm)::update();
317}
318
319// ----------------------------------------------------------------------------------------
320// nld_CS
321// ----------------------------------------------------------------------------------------
322
323NETLIB_START(CS)
324{
325   NETLIB_NAME(twoterm)::start();
326
327   register_param("I", m_I, 1.0);
328
329   register_terminal("P", m_P);
330   register_terminal("N", m_N);
331}
332
333NETLIB_RESET(CS)
334{
335   NETLIB_NAME(twoterm)::reset();
336   this->set(0.0, 0.0, m_I);
337}
338
339NETLIB_UPDATE(CS)
340{
341   NETLIB_NAME(twoterm)::update();
342}
343
344NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/analog/nld_twoterm.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_twoterm.h
5 *
6 * Devices with two terminals ...
7 *
8 *
9 *       (k)
10 *  +-----T-----+
11 *  |     |     |
12 *  |  +--+--+  |
13 *  |  |     |  |
14 *  |  R     |  |
15 *  |  R     |  |
16 *  |  R     I  |
17 *  |  |     I  |  Device n
18 *  |  V+    I  |
19 *  |  V     |  |
20 *  |  V-    |  |
21 *  |  |     |  |
22 *  |  +--+--+  |
23 *  |     |     |
24 *  +-----T-----+
25 *       (l)
26 *
27 *  This is a resistance in series to a voltage source and paralleled by a
28 *  current source. This is suitable to model voltage sources, current sources,
29 *  resistors, capacitors, inductances and diodes.
30 *
31 */
32
33#ifndef NLD_TWOTERM_H_
34#define NLD_TWOTERM_H_
35
36#include "nl_base.h"
37
38// -----------------------------------------------------------------------------
39// Macros
40// -----------------------------------------------------------------------------
41
42#define RES(_name, _R)                                                         \
43      NET_REGISTER_DEV(RES, _name)                                           \
44      NETDEV_PARAMI(_name, R, _R)
45
46#define POT(_name, _R)                                                         \
47      NET_REGISTER_DEV(POT, _name)                                           \
48      NETDEV_PARAMI(_name, R, _R)
49
50/* Does not have pin 3 connected */
51#define POT2(_name, _R)                                                        \
52      NET_REGISTER_DEV(POT2, _name)                                          \
53      NETDEV_PARAMI(_name, R, _R)
54
55
56#define CAP(_name, _C)                                                         \
57      NET_REGISTER_DEV(CAP, _name)                                           \
58      NETDEV_PARAMI(_name, C, _C)
59
60/* Generic Diode */
61#define DIODE(_name,  _model)                                                  \
62      NET_REGISTER_DEV(DIODE, _name)                                         \
63      NETDEV_PARAMI(_name, MODEL, _model)
64
65#define VS(_name, _V)                                                          \
66      NET_REGISTER_DEV(VS, _name)                                            \
67      NETDEV_PARAMI(_name, V, _V)
68
69#define CS(_name, _I)                                                          \
70      NET_REGISTER_DEV(CS, _name)                                            \
71      NETDEV_PARAMI(_name, I, _I)
72
73// -----------------------------------------------------------------------------
74// Generic macros
75// -----------------------------------------------------------------------------
76
77
78#ifdef RES_R
79// FIXME: avoid compile fails
80// #warning "Do not include rescap.h in a netlist environment"
81#endif
82
83#define RES_R(res) ((double)(res))
84#define RES_K(res) ((double)(res) * 1e3)
85#define RES_M(res) ((double)(res) * 1e6)
86#define CAP_U(cap) ((double)(cap) * 1e-6)
87#define CAP_N(cap) ((double)(cap) * 1e-9)
88#define CAP_P(cap) ((double)(cap) * 1e-12)
89#define IND_U(ind) ((double)(ind) * 1e-6)
90#define IND_N(ind) ((double)(ind) * 1e-9)
91#define IND_P(ind) ((double)(ind) * 1e-12)
92
93// -----------------------------------------------------------------------------
94// Implementation
95// -----------------------------------------------------------------------------
96
97NETLIB_NAMESPACE_DEVICES_START()
98
99// -----------------------------------------------------------------------------
100// nld_twoterm
101// -----------------------------------------------------------------------------
102
103class NETLIB_NAME(twoterm) : public device_t
104{
105public:
106   ATTR_COLD NETLIB_NAME(twoterm)(const family_t afamily);
107   ATTR_COLD NETLIB_NAME(twoterm)();
108
109   terminal_t m_P;
110   terminal_t m_N;
111
112   virtual NETLIB_UPDATE_TERMINALSI()
113   {
114   }
115
116   ATTR_HOT /* inline */ void set(const nl_double G, const nl_double V, const nl_double I)
117   {
118      /*      GO, GT, I                */
119      m_P.set( G,  G, (  V) * G - I);
120      m_N.set( G,  G, ( -V) * G + I);
121   }
122
123   ATTR_HOT /* inline */ nl_double deltaV() const
124   {
125      return m_P.net().as_analog().Q_Analog() - m_N.net().as_analog().Q_Analog();
126   }
127
128   ATTR_HOT void set_mat(nl_double a11, nl_double a12, nl_double a21, nl_double a22, nl_double r1, nl_double r2)
129   {
130      /*      GO, GT, I                */
131      m_P.set(-a12, a11, -r1);
132      m_N.set(-a21, a22, -r2);
133   }
134
135protected:
136   virtual void start();
137   virtual void reset();
138   ATTR_HOT void update();
139
140private:
141};
142
143// -----------------------------------------------------------------------------
144// nld_R
145// -----------------------------------------------------------------------------
146
147class NETLIB_NAME(R_base) : public NETLIB_NAME(twoterm)
148{
149public:
150   ATTR_COLD NETLIB_NAME(R_base)() : NETLIB_NAME(twoterm)(RESISTOR) { }
151
152   inline void set_R(const nl_double R)
153   {
154      set(NL_FCONST(1.0) / R, 0.0, 0.0);
155   }
156
157protected:
158   virtual void start();
159   virtual void reset();
160   ATTR_HOT void update();
161};
162
163NETLIB_DEVICE_WITH_PARAMS_DERIVED(R, R_base,
164   param_double_t m_R;
165);
166
167// -----------------------------------------------------------------------------
168// nld_POT
169// -----------------------------------------------------------------------------
170
171NETLIB_DEVICE_WITH_PARAMS(POT,
172   NETLIB_NAME(R_base) m_R1;
173   NETLIB_NAME(R_base) m_R2;
174
175   param_double_t m_R;
176   param_double_t m_Dial;
177   param_logic_t m_DialIsLog;
178);
179
180NETLIB_DEVICE_WITH_PARAMS(POT2,
181   NETLIB_NAME(R_base) m_R1;
182
183   param_double_t m_R;
184   param_double_t m_Dial;
185   param_logic_t m_DialIsLog;
186   param_logic_t m_Reverse;
187);
188
189
190// -----------------------------------------------------------------------------
191// nld_C
192// -----------------------------------------------------------------------------
193
194class NETLIB_NAME(C) : public NETLIB_NAME(twoterm)
195{
196public:
197   ATTR_COLD NETLIB_NAME(C)() : NETLIB_NAME(twoterm)(CAPACITOR), m_GParallel(0.0) { }
198
199   ATTR_HOT void step_time(const nl_double st);
200
201   param_double_t m_C;
202
203protected:
204   virtual void start();
205   virtual void reset();
206   virtual void update_param();
207   ATTR_HOT void update();
208
209private:
210   nl_double m_GParallel;
211
212};
213
214
215// -----------------------------------------------------------------------------
216// A generic diode model to be used in other devices (Diode, BJT ...)
217// -----------------------------------------------------------------------------
218
219class generic_diode
220{
221public:
222   ATTR_COLD generic_diode();
223
224   ATTR_HOT inline void update_diode(const nl_double nVd)
225   {
226#if 1
227      if (nVd < NL_FCONST(-5.0) * m_Vt)
228      {
229         m_Vd = nVd;
230         m_G = m_gmin;
231         m_Id = - m_Is;
232      }
233      else if (nVd < m_Vcrit)
234      {
235         m_Vd = nVd;
236         //m_Vd = m_Vd + 10.0 * m_Vt * std::tanh((nVd - m_Vd) / 10.0 / m_Vt);
237         const nl_double eVDVt = nl_math::exp(m_Vd * m_VtInv);
238         m_Id = m_Is * (eVDVt - NL_FCONST(1.0));
239         m_G = m_Is * m_VtInv * eVDVt + m_gmin;
240      }
241      else
242      {
243#if 1
244         const nl_double a = std::max((nVd - m_Vd) * m_VtInv, NL_FCONST(0.5) - NL_FCONST(1.0));
245         m_Vd = m_Vd + nl_math::e_log1p(a) * m_Vt;
246#else
247         m_Vd = m_Vd + 10.0 * m_Vt * std::tanh((nVd - m_Vd) / 10.0 / m_Vt);
248#endif
249         const nl_double eVDVt = nl_math::exp(m_Vd * m_VtInv);
250         m_Id = m_Is * (eVDVt - NL_FCONST(1.0));
251
252         m_G = m_Is * m_VtInv * eVDVt + m_gmin;
253      }
254#else
255      m_Vd = m_Vd + 20.0 * m_Vt * std::tanh((nVd - m_Vd) / 20.0 / m_Vt);
256      const nl_double eVDVt = nl_math::exp(m_Vd * m_VtInv);
257      m_Id = m_Is * (eVDVt - NL_FCONST(1.0));
258      m_G = m_Is * m_VtInv * eVDVt + m_gmin;
259#endif
260   }
261
262   ATTR_COLD void set_param(const nl_double Is, const nl_double n, nl_double gmin);
263
264   ATTR_HOT inline nl_double I() const { return m_Id; }
265   ATTR_HOT inline nl_double G() const { return m_G; }
266   ATTR_HOT inline nl_double Ieq() const { return (m_Id - m_Vd * m_G); }
267   ATTR_HOT inline nl_double Vd() const { return m_Vd; }
268
269   /* owning object must save those ... */
270
271   ATTR_COLD void save(pstring name, object_t &parent);
272
273private:
274   nl_double m_Vd;
275   nl_double m_Id;
276   nl_double m_G;
277
278   nl_double m_Vt;
279   nl_double m_Is;
280   nl_double m_n;
281   nl_double m_gmin;
282
283   nl_double m_VtInv;
284   nl_double m_Vcrit;
285};
286
287// -----------------------------------------------------------------------------
288// nld_D
289// -----------------------------------------------------------------------------
290
291class NETLIB_NAME(D) : public NETLIB_NAME(twoterm)
292{
293public:
294   ATTR_COLD NETLIB_NAME(D)() : NETLIB_NAME(twoterm)(DIODE) { }
295
296   NETLIB_UPDATE_TERMINALSI();
297
298   param_model_t m_model;
299
300protected:
301   virtual void start();
302   virtual void update_param();
303   ATTR_HOT void update();
304
305   generic_diode m_D;
306};
307
308// -----------------------------------------------------------------------------
309// nld_VS - Voltage source
310//
311// netlist voltage source must have inner resistance
312// -----------------------------------------------------------------------------
313
314class NETLIB_NAME(VS) : public NETLIB_NAME(twoterm)
315{
316public:
317   ATTR_COLD NETLIB_NAME(VS)() : NETLIB_NAME(twoterm)(VS) { }
318
319protected:
320   virtual void start();
321   virtual void reset();
322   ATTR_HOT void update();
323
324   param_double_t m_R;
325   param_double_t m_V;
326};
327
328// -----------------------------------------------------------------------------
329// nld_CS - Current source
330// -----------------------------------------------------------------------------
331
332class NETLIB_NAME(CS) : public NETLIB_NAME(twoterm)
333{
334public:
335   ATTR_COLD NETLIB_NAME(CS)() : NETLIB_NAME(twoterm)(CS) { }
336
337protected:
338   virtual void start();
339   virtual void reset();
340   ATTR_HOT void update();
341
342   param_double_t m_I;
343};
344
345
346NETLIB_NAMESPACE_DEVICES_END()
347
348#endif /* NLD_TWOTERM_H_ */
trunk/src/lib/netlist/build/makefile
r0r249195
1###########################################################################
2#
3#   makefile
4#
5#   Core makefile for building MAME and derivatives
6#
7#   Copyright (c) Nicola Salmoria and the MAME Team.
8#   Visit http://mamedev.org for licensing and usage restrictions.
9#
10###########################################################################
11
12OBJ = obj
13SRC = ..
14
15#-fuse-ld=gold -Wpedantic -march=native -march=native
16
17# LTO = -flto=4  -fuse-linker-plugin -flto-partition=balanced -Wodr
18
19CDEFS = -DPSTANDALONE=1 -DPTR64=1
20#-Werror
21CFLAGS =  $(LTO) -g -O3 -std=c++98  -march=native -msse4.2 -Wall -Wpedantic -Wsign-compare -Wextra -Wno-long-long -Wno-unused-parameter -Wno-unused-result -Wno-variadic-macros -I..
22LDFLAGS = $(LTO) -g -O3 -std=c++98
23#CFLAGS =  $(LTO) -g -O3 -std=c++11   -Wall -Wpedantic -Wsign-compare -Wextra -Isrc
24#LDFLAGS = $(LTO) -g -O3 -std=c++11   
25
26CC = @g++-5
27LD = @g++-5
28MD = @mkdir
29RM = @rm
30
31TARGETS = nltool nlwav
32
33NLOBJ = $(OBJ)
34POBJ = $(OBJ)/plib
35
36OBJDIRS = $(OBJ) \
37        $(OBJ)/analog \
38        $(OBJ)/solver \
39        $(OBJ)/devices \
40        $(OBJ)/plib \
41        $(OBJ)/devices \
42        $(OBJ)/macro \
43        $(OBJ)/tools \
44        $(OBJ)/prg \
45       
46
47OBJS = $(POBJS) $(NLOBJS)
48
49POBJS := \
50   $(POBJ)/pstring.o \
51   $(POBJ)/palloc.o \
52   $(POBJ)/pparser.o \
53   $(POBJ)/pstate.o \
54   $(POBJ)/pstream.o \
55
56NLOBJS := \
57   $(NLOBJ)/nl_base.o \
58   $(NLOBJ)/nl_parser.o \
59   $(NLOBJ)/nl_setup.o \
60   $(NLOBJ)/nl_factory.o \
61   $(NLOBJ)/analog/nld_bjt.o \
62   $(NLOBJ)/analog/nld_fourterm.o \
63   $(NLOBJ)/analog/nld_switches.o \
64   $(NLOBJ)/analog/nld_twoterm.o \
65   $(NLOBJ)/analog/nld_opamps.o \
66   $(NLOBJ)/devices/nld_4020.o \
67   $(NLOBJ)/devices/nld_4066.o \
68   $(NLOBJ)/devices/nld_7400.o \
69   $(NLOBJ)/devices/nld_7402.o \
70   $(NLOBJ)/devices/nld_7404.o \
71   $(NLOBJ)/devices/nld_7408.o \
72   $(NLOBJ)/devices/nld_7410.o \
73   $(NLOBJ)/devices/nld_7411.o \
74   $(NLOBJ)/devices/nld_7420.o \
75   $(NLOBJ)/devices/nld_7425.o \
76   $(NLOBJ)/devices/nld_7427.o \
77   $(NLOBJ)/devices/nld_7430.o \
78   $(NLOBJ)/devices/nld_7432.o \
79   $(NLOBJ)/devices/nld_7437.o \
80   $(NLOBJ)/devices/nld_7448.o \
81   $(NLOBJ)/devices/nld_7450.o \
82   $(NLOBJ)/devices/nld_7474.o \
83   $(NLOBJ)/devices/nld_7483.o \
84   $(NLOBJ)/devices/nld_7486.o \
85   $(NLOBJ)/devices/nld_7490.o \
86   $(NLOBJ)/devices/nld_7493.o \
87   $(NLOBJ)/devices/nld_74107.o \
88   $(NLOBJ)/devices/nld_74123.o \
89   $(NLOBJ)/devices/nld_74153.o \
90   $(NLOBJ)/devices/nld_74175.o \
91   $(NLOBJ)/devices/nld_74192.o \
92   $(NLOBJ)/devices/nld_74193.o \
93   $(NLOBJ)/devices/nld_74279.o \
94   $(NLOBJ)/devices/nld_74ls629.o \
95   $(NLOBJ)/devices/nld_82S16.o \
96   $(NLOBJ)/devices/nld_9310.o \
97   $(NLOBJ)/devices/nld_9312.o \
98   $(NLOBJ)/devices/nld_9316.o \
99   $(NLOBJ)/devices/nld_mm5837.o \
100   $(NLOBJ)/devices/nld_ne555.o \
101   $(NLOBJ)/devices/nld_r2r_dac.o \
102   $(NLOBJ)/devices/nld_legacy.o \
103   $(NLOBJ)/devices/net_lib.o \
104   $(NLOBJ)/devices/nld_log.o \
105   $(NLOBJ)/devices/nld_system.o \
106   $(NLOBJ)/devices/nld_truthtable.o \
107   $(NLOBJ)/macro/nlm_cd4xxx.o \
108   $(NLOBJ)/macro/nlm_opamp.o \
109   $(NLOBJ)/macro/nlm_other.o \
110   $(NLOBJ)/macro/nlm_ttl74xx.o \
111   $(NLOBJ)/solver/nld_solver.o \
112   $(NLOBJ)/tools/nl_convert.o \
113
114all:   maketree $(TARGETS)
115
116#-------------------------------------------------
117# clean
118#-------------------------------------------------
119
120clean:
121   $(RM) -rf $(OBJS) $(TARGETS)
122
123#-------------------------------------------------
124# nltool
125#-------------------------------------------------
126
127nltool: $(OBJ)/prg/nltool.o $(OBJS)
128   @echo Linking $@...
129   $(LD) -o $@ $(LDFLAGS) $^ $(LIBS)
130
131nlwav: $(OBJ)/prg/nlwav.o $(OBJS)
132   @echo Linking $@...
133   $(LD) -o $@ $(LDFLAGS) $^ $(LIBS)
134
135#-------------------------------------------------
136# directories
137#-------------------------------------------------
138
139$(sort $(OBJDIRS)):
140   $(MD) -p $@
141
142maketree: $(sort $(OBJDIRS))
143
144
145#-------------------------------------------------
146# generic rules
147#-------------------------------------------------
148
149$(OBJ)/%.o: $(SRC)/%.c
150   @echo Compiling $<...
151   $(CC) $(CDEFS) $(CFLAGS) -c $< -o $@
152
153$(OBJ)/%.pp: $(SRC)/%.c | $(OSPREBUILD)
154   @echo Compiling $<...
155   $(CC) $(CDEFS) $(CFLAGS) -E $< -o $@
156
157$(OBJ)/%.s: $(SRC)/%.c | $(OSPREBUILD)
158   @echo Compiling $<...
159   $(CC) $(CDEFS) $(CFLAGS) -S $< -o $@
160
161$(OBJ)/%.a:
162   @echo Archiving $@...
163   $(RM) $@
164   $(AR) $(ARFLAGS) $@ $^
165
166
trunk/src/lib/netlist/devices/net_lib.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/***************************************************************************
4
5    netlib.c
6
7    Discrete netlist implementation.
8
9****************************************************************************/
10
11#include "net_lib.h"
12#include "nld_system.h"
13#include "nl_factory.h"
14
15NETLIST_START(diode_models)
16   NET_MODEL("D _(IS=1e-15 N=1)")
17
18   NET_MODEL("1N914 D(Is=2.52n Rs=.568 N=1.752 Cjo=4p M=.4 tt=20n Iave=200m Vpk=75 mfg=OnSemi type=silicon)")
19   NET_MODEL("1N4001 D(Is=14.11n N=1.984 Rs=33.89m Ikf=94.81 Xti=3 Eg=1.11 Cjo=25.89p M=.44 Vj=.3245 Fc=.5 Bv=75 Ibv=10u Tt=5.7u Iave=1 Vpk=50 mfg=GI type=silicon)")
20   NET_MODEL("1N4148 D(Is=2.52n Rs=.568 N=1.752 Cjo=4p M=.4 tt=20n Iave=200m Vpk=75 mfg=OnSemi type=silicon)")
21   NET_MODEL("1S1588 D(Is=2.52n Rs=.568 N=1.752 Cjo=4p M=.4 tt=20n Iave=200m Vpk=75)")
22   NET_MODEL("LedRed D(IS=93.2p RS=42M N=3.73 BV=4 IBV=10U CJO=2.97P VJ=.75 M=.333 TT=4.32U Iave=40m Vpk=4 type=LED)")
23   NET_MODEL("LedGreen D(IS=93.2p RS=42M N=4.61 BV=4 IBV=10U CJO=2.97P VJ=.75 M=.333 TT=4.32U Iave=40m Vpk=4 type=LED)")
24   NET_MODEL("LedBlue D(IS=93.2p RS=42M N=7.47 BV=5 IBV=10U CJO=2.97P VJ=.75 M=.333 TT=4.32U Iave=40m Vpk=5 type=LED)")
25   NET_MODEL("LedWhite D(Is=0.27n Rs=5.65 N=6.79 Cjo=42p Iave=30m Vpk=5 type=LED)")
26
27NETLIST_END()
28
29NETLIST_START(bjt_models)
30   NET_MODEL("NPN _(IS=1e-15 BF=100 NF=1 BR=1 NR=1)")
31   NET_MODEL("PNP _(IS=1e-15 BF=100 NF=1 BR=1 NR=1)")
32
33   NET_MODEL("2SA1015 PNP(Is=295.1E-18 Xti=3 Eg=1.11 Vaf=100 Bf=110 Xtb=1.5 Br=10.45 Rc=15 Cjc=66.2p Mjc=1.054 Vjc=.75 Fc=.5 Cje=5p Mje=.3333 Vje=.75 Tr=10n Tf=1.661n VCEO=45V ICrating=150M MFG=Toshiba)")
34   NET_MODEL("2SC1815 NPN(Is=2.04f Xti=3 Eg=1.11 Vaf=6 Bf=400 Ikf=20m Xtb=1.5 Br=3.377 Rc=1 Cjc=1p Mjc=.3333 Vjc=.75 Fc=.5 Cje=25p Mje=.3333 Vje=.75 Tr=450n Tf=20n Itf=0 Vtf=0 Xtf=0 VCEO=45V ICrating=150M MFG=Toshiba)")
35
36   NET_MODEL("2N3643 NPN(IS=14.34E-15 ISE=14.34E-15 ISC=0 XTI=3 BF=255.9 BR=6.092 IKF=0.2847 IKR=0 XTB=1.5 VAF=74.03 VAR=28 VJE=0.65 VJC=0.65 RE=0.1 RC=1 RB=10 CJE=22.01E-12 CJC=7.306E-12 XCJC=0.75 FC=0.5 NF=1 NR=1 NE=1.307 NC=2 MJE=0.377 MJC=0.3416 TF=411.1E-12 TR=46.91E-9 ITF=0.6 VTF=1.7 XTF=3 EG=1.11 KF=0 AF=1 VCEO=30 ICRATING=500m MFG=NSC)")
37   NET_MODEL("2N3645 PNP(IS=650.6E-18 ISE=54.81E-15 ISC=0 XTI=3 BF=231.7 BR=3.563 IKF=1.079 IKR=0 XTB=1.5 VAF=115.7 VAR=35 VJE=0.65 VJC=0.65 RE=0.15 RC=0.715 RB=10 CJE=19.82E-12 CJC=14.76E-12 XCJC=0.75 FC=0.5 NF=1 NR=1 NE=1.829 NC=2 MJE=0.3357 MJC=0.5383 TF=603.7E-12 TR=111.3E-9 ITF=0.65 VTF=5 XTF=1.7 EG=1.11 KF=0 AF=1 VCEO=60 ICRATING=500m MFG=NSC)")
38   // 3644 = 3645 Difference between 3644 and 3645 is voltage rating. 3644: VCBO=45, 3645: VCBO=60
39   NET_MODEL("2N3644 PNP(IS=650.6E-18 ISE=54.81E-15 ISC=0 XTI=3 BF=231.7 BR=3.563 IKF=1.079 IKR=0 XTB=1.5 VAF=115.7 VAR=35 VJE=0.65 VJC=0.65 RE=0.15 RC=0.715 RB=10 CJE=19.82E-12 CJC=14.76E-12 XCJC=0.75 FC=0.5 NF=1 NR=1 NE=1.829 NC=2 MJE=0.3357 MJC=0.5383 TF=603.7E-12 TR=111.3E-9 ITF=0.65 VTF=5 XTF=1.7 EG=1.11 KF=0 AF=1 VCEO=60 ICRATING=500m MFG=NSC)")
40   // 2N5190 = BC817-25
41   NET_MODEL("2N5190 NPN(IS=9.198E-14 NF=1.003 ISE=4.468E-16 NE=1.65 BF=338.8 IKF=0.4913 VAF=107.9 NR=1.002 ISC=5.109E-15 NC=1.071 BR=29.48 IKR=0.193 VAR=25 RB=1 IRB=1000 RBM=1 RE=0.2126 RC=0.143 XTB=0 EG=1.11 XTI=3 CJE=3.825E-11 VJE=0.7004 MJE=0.364 TF=5.229E-10 XTF=219.7 VTF=3.502 ITF=7.257 PTF=0 CJC=1.27E-11 VJC=0.4431 MJC=0.3983 XCJC=0.4555 TR=7E-11 CJS=0 VJS=0.75 MJS=0.333 FC=0.905 Vceo=45 Icrating=500m mfg=Philips)")
42   NET_MODEL("2SC945 NPN(IS=3.577E-14 BF=2.382E+02 NF=1.01 VAF=1.206E+02 IKF=3.332E-01 ISE=3.038E-16 NE=1.205 BR=1.289E+01 NR=1.015 VAR=1.533E+01 IKR=2.037E-01 ISC=3.972E-14 NC=1.115 RB=3.680E+01 IRB=1.004E-04 RBM=1 RE=8.338E-01 RC=1.557E+00 CJE=1.877E-11 VJE=7.211E-01 MJE=3.486E-01 TF=4.149E-10 XTF=1.000E+02 VTF=9.956 ITF=5.118E-01 PTF=0 CJC=6.876p VJC=3.645E-01 MJC=3.074E-01 TR=5.145E-08 XTB=1.5 EG=1.11 XTI=3 FC=0.5 Vceo=50 Icrating=100m MFG=NEC)")
43
44   NET_MODEL("BC237B NPN(IS=1.8E-14 ISE=5.0E-14 ISC=1.72E-13 XTI=3 BF=400 BR=35.5 IKF=0.14 IKR=0.03 XTB=1.5 VAF=80 VAR=12.5 VJE=0.58 VJC=0.54 RE=0.6 RC=0.25 RB=0.56 CJE=13E-12 CJC=4E-12 XCJC=0.75 FC=0.5 NF=0.9955 NR=1.005 NE=1.46 NC=1.27 MJE=0.33 MJC=0.33 TF=0.64E-9 TR=50.72E-9 EG=1.11 KF=0 AF=1 VCEO=45V ICRATING=100M MFG=ZETEX)")
45   NET_MODEL("BC556B PNP(IS=3.83E-14 NF=1.008 ISE=1.22E-14 NE=1.528 BF=344.4 IKF=0.08039 VAF=21.11 NR=1.005 ISC=2.85E-13 NC=1.28 BR=14.84 IKR=0.047 VAR=32.02 RB=1 IRB=1.00E-06 RBM=1 RE=0.6202 RC=0.5713 XTB=0 EG=1.11 XTI=3 CJE=1.23E-11 VJE=0.6106 MJE=0.378 TF=5.60E-10 XTF=3.414 VTF=5.23 ITF=0.1483 PTF=0 CJC=1.08E-11 VJC=0.1022 MJC=0.3563 XCJC=0.6288 TR=1.00E-32 CJS=0 VJS=0.75 MJS=0.333 FC=0.8027 Vceo=65 Icrating=100m mfg=Philips)")
46   NET_MODEL("BC817-25 NPN(IS=9.198E-14 NF=1.003 ISE=4.468E-16 NE=1.65 BF=338.8 IKF=0.4913 VAF=107.9 NR=1.002 ISC=5.109E-15 NC=1.071 BR=29.48 IKR=0.193 VAR=25 RB=1 IRB=1000 RBM=1 RE=0.2126 RC=0.143 XTB=0 EG=1.11 XTI=3 CJE=3.825E-11 VJE=0.7004 MJE=0.364 TF=5.229E-10 XTF=219.7 VTF=3.502 ITF=7.257 PTF=0 CJC=1.27E-11 VJC=0.4431 MJC=0.3983 XCJC=0.4555 TR=7E-11 CJS=0 VJS=0.75 MJS=0.333 FC=0.905 Vceo=45 Icrating=500m mfg=Philips)")
47NETLIST_END()
48
49NETLIST_START(family_models)
50   NET_MODEL("FAMILY _(TYPE=CUSTOM IVL=0.8 IVH=2.0 OVL=0.1 OVH=4.0 ORL=1.0 ORH=130.0)")
51   NET_MODEL("OPAMP _()")
52
53   NET_MODEL("74XXOC FAMILY(IVL=0.8 IVH=2.0 OVL=0.1 OVH=4.95 ORL=10.0 ORH=1.0e8)")
54   NET_MODEL("CD4XXX FAMILY(TYPE=CD4XXX)")
55NETLIST_END()
56
57
58#define xstr(s) # s
59#define ENTRY1(_nic, _name, _defparam) factory.register_device<_nic>( # _name, xstr(_nic), _defparam );
60#define ENTRY(_nic, _name, _defparam) ENTRY1(NETLIB_NAME(_nic), _name, _defparam)
61
62NETLIB_NAMESPACE_DEVICES_START()
63
64void initialize_factory(factory_list_t &factory)
65{
66   ENTRY(R,                    RES,                    "R")
67   ENTRY(POT,                  POT,                    "R")
68   ENTRY(POT2,                 POT2,                   "R")
69   ENTRY(C,                    CAP,                    "C")
70   ENTRY(D,                    DIODE,                  "MODEL")
71   ENTRY(VCVS,                 VCVS,                   "-")
72   ENTRY(VCCS,                 VCCS,                   "-")
73   ENTRY(CCCS,                 CCCS,                   "-")
74   ENTRY(LVCCS,                LVCCS,                  "-")
75   ENTRY(VS,                   VS,                     "V")
76   ENTRY(CS,                   CS,                     "I")
77   ENTRY(OPAMP,                OPAMP,                  "MODEL")
78   ENTRY(dummy_input,          DUMMY_INPUT,            "-")
79   ENTRY(frontier,             FRONTIER_DEV,           "+I,G,Q")   // not intended to be used directly
80   ENTRY(function,             AFUNC,                  "N,FUNC")   // only for macro devices - NO FEEDBACK loops
81   ENTRY(QBJT_EB,              QBJT_EB,                "MODEL")
82   ENTRY(QBJT_switch,          QBJT_SW,                "MODEL")
83   ENTRY(logic_input,          TTL_INPUT,              "IN")
84   ENTRY(logic_input,          LOGIC_INPUT,            "IN,FAMILY")
85   ENTRY(analog_input,         ANALOG_INPUT,           "IN")
86   ENTRY(log,                  LOG,                    "+I")
87   ENTRY(logD,                 LOGD,                   "+I,I2")
88   ENTRY(clock,                CLOCK,                  "FREQ")
89   ENTRY(extclock,             EXTCLOCK,               "FREQ")
90   ENTRY(mainclock,            MAINCLOCK,              "FREQ")
91   ENTRY(gnd,                  GND,                    "-")
92   ENTRY(netlistparams,        PARAMETER,              "-")
93   ENTRY(solver,               SOLVER,                 "FREQ")
94   ENTRY(res_sw,               RES_SWITCH,             "+IN,P1,P2")
95   ENTRY(switch1,              SWITCH,                 "-")
96   ENTRY(switch2,              SWITCH2,                "-")
97   ENTRY(nicRSFF,              NETDEV_RSFF,            "+S,R")
98   ENTRY(nicDelay,             NETDEV_DELAY,            "-")
99   ENTRY(7400,                 TTL_7400_NAND,          "+A,B")
100   ENTRY(7402,                 TTL_7402_NOR,           "+A,B")
101   ENTRY(7404,                 TTL_7404_INVERT,        "+A")
102   ENTRY(7408,                 TTL_7408_AND,           "+A,B")
103   ENTRY(7410,                 TTL_7410_NAND,          "+A,B,C")
104   ENTRY(7411,                 TTL_7411_AND,           "+A,B,C")
105   ENTRY(7420,                 TTL_7420_NAND,          "+A,B,C,D")
106   ENTRY(7425,                 TTL_7425_NOR,           "+A,B,C,D")
107   ENTRY(7427,                 TTL_7427_NOR,           "+A,B,C")
108   ENTRY(7430,                 TTL_7430_NAND,          "+A,B,C,D,E,F,G,H")
109   ENTRY(7432,                 TTL_7432_OR,            "+A,B")
110   ENTRY(7437,                 TTL_7437_NAND,          "+A,B")
111   ENTRY(7450,                 TTL_7450_ANDORINVERT,   "+A,B,C,D")
112   ENTRY(7486,                 TTL_7486_XOR,           "+A,B")
113   ENTRY(7448,                 TTL_7448,               "+A,B,C,D,LTQ,BIQ,RBIQ")
114   ENTRY(7474,                 TTL_7474,               "+CLK,D,CLRQ,PREQ")
115   ENTRY(7483,                 TTL_7483,               "+A1,A2,A3,A4,B1,B2,B3,B4,C0")
116   ENTRY(7490,                 TTL_7490,               "+A,B,R1,R2,R91,R92")
117   ENTRY(7493,                 TTL_7493,               "+CLKA,CLKB,R1,R2")
118   ENTRY(74107,                TTL_74107,              "+CLK,J,K,CLRQ")
119   ENTRY(74107A,               TTL_74107A,             "+CLK,J,K,CLRQ")
120   ENTRY(74123,                TTL_74123,              "-")
121   ENTRY(74153,                TTL_74153,              "+C0,C1,C2,C3,A,B,G")
122   ENTRY(74175,                TTL_74175,              "-")
123   ENTRY(74192,                TTL_74192,              "-")
124   ENTRY(74193,                TTL_74193,              "-")
125   //ENTRY(74279,              TTL_74279,              "-") // only dip available
126   ENTRY(SN74LS629,            SN74LS629,              "CAP")
127   ENTRY(82S16,                TTL_82S16,              "-")
128   ENTRY(9310,                 TTL_9310,               "-")
129   ENTRY(9312,                 TTL_9312,               "-")
130   ENTRY(9316,                 TTL_9316,               "+CLK,ENP,ENT,CLRQ,LOADQ,A,B,C,D")
131   ENTRY(CD4020,               CD4020,                 "")
132   ENTRY(CD4066_GATE,          CD4066_GATE,            "")
133   /* entries with suffix _WI are legacy only */
134   ENTRY(CD4020,               CD4020_WI,              "+IP,RESET,VDD,VSS")
135   //ENTRY(4066,                 CD_4066,              "+A,B")
136   ENTRY(NE555,                NE555,                  "-")
137   ENTRY(r2r_dac,              R2R_DAC,                "+VIN,R,N")
138   ENTRY(4538_dip,             CD4538_DIP,             "-")
139   ENTRY(7400_dip,             TTL_7400_DIP,           "-")
140   ENTRY(7402_dip,             TTL_7402_DIP,           "-")
141   ENTRY(7404_dip,             TTL_7404_DIP,           "-")
142   ENTRY(7408_dip,             TTL_7408_DIP,           "-")
143   ENTRY(7410_dip,             TTL_7410_DIP,           "-")
144   ENTRY(7411_dip,             TTL_7411_DIP,           "-")
145   ENTRY(7420_dip,             TTL_7420_DIP,           "-")
146   ENTRY(7425_dip,             TTL_7425_DIP,           "-")
147   ENTRY(7427_dip,             TTL_7427_DIP,           "-")
148   ENTRY(7430_dip,             TTL_7430_DIP,           "-")
149   ENTRY(7432_dip,             TTL_7432_DIP,           "-")
150   ENTRY(7437_dip,             TTL_7437_DIP,           "-")
151   ENTRY(7448_dip,             TTL_7448_DIP,           "-")
152   ENTRY(7450_dip,             TTL_7450_DIP,           "-")
153   ENTRY(7474_dip,             TTL_7474_DIP,           "-")
154   ENTRY(7483_dip,             TTL_7483_DIP,           "-")
155   ENTRY(7486_dip,             TTL_7486_DIP,           "-")
156   ENTRY(7490_dip,             TTL_7490_DIP,           "-")
157   ENTRY(7493_dip,             TTL_7493_DIP,           "-")
158   ENTRY(74107_dip,            TTL_74107_DIP,          "-")
159   ENTRY(74123_dip,            TTL_74123_DIP,          "-")
160   ENTRY(74153_dip,            TTL_74153_DIP,          "-")
161   ENTRY(74175_dip,            TTL_74175_DIP,          "-")
162   ENTRY(74192_dip,            TTL_74192_DIP,          "-")
163   ENTRY(74193_dip,            TTL_74193_DIP,          "-")
164   ENTRY(74279_dip,            TTL_74279_DIP,          "-")
165   ENTRY(82S16_dip,            TTL_82S16_DIP,          "-")
166   ENTRY(9602_dip,             TTL_9602_DIP,           "-")
167   ENTRY(9310_dip,             TTL_9310_DIP,           "-")
168   ENTRY(9312_dip,             TTL_9312_DIP,           "-")
169   ENTRY(9316_dip,             TTL_9316_DIP,           "-")
170   ENTRY(SN74LS629_dip,        SN74LS629_DIP,          "1.CAP1,2.CAP2")
171   ENTRY(NE555_dip,            NE555_DIP,              "-")
172   ENTRY(MM5837_dip,           MM5837_DIP,             "-")
173}
174
175NETLIB_NAMESPACE_DEVICES_END()
176
177namespace netlist
178{
179   void initialize_factory(factory_list_t &factory)
180   {
181      devices::initialize_factory(factory);
182   }
183}
trunk/src/lib/netlist/devices/net_lib.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/***************************************************************************
4
5    net_lib.h
6
7    Discrete netlist implementation.
8
9****************************************************************************/
10
11#ifndef NET_LIB_H
12#define NET_LIB_H
13
14#include "nl_base.h"
15#include "nld_signal.h"
16#include "nld_system.h"
17
18#include "nld_4020.h"
19#include "nld_4066.h"
20#include "nld_7400.h"
21#include "nld_7402.h"
22#include "nld_7404.h"
23#include "nld_7408.h"
24#include "nld_7410.h"
25#include "nld_7411.h"
26#include "nld_7420.h"
27#include "nld_7425.h"
28#include "nld_7427.h"
29#include "nld_7430.h"
30#include "nld_7432.h"
31#include "nld_7437.h"
32#include "nld_7448.h"
33#include "nld_7450.h"
34#include "nld_7474.h"
35#include "nld_7483.h"
36#include "nld_7486.h"
37#include "nld_7490.h"
38#include "nld_7493.h"
39#include "nld_74107.h"
40#include "nld_74123.h"
41#include "nld_74153.h"
42#include "nld_74175.h"
43#include "nld_74192.h"
44#include "nld_74193.h"
45#include "nld_74279.h"
46#include "nld_74ls629.h"
47#include "nld_82S16.h"
48#include "nld_9310.h"
49#include "nld_9312.h"
50#include "nld_9316.h"
51
52#include "nld_ne555.h"
53#include "nld_mm5837.h"
54
55#include "nld_r2r_dac.h"
56
57#include "nld_log.h"
58
59#include "macro/nlm_cd4xxx.h"
60#include "macro/nlm_ttl74xx.h"
61#include "macro/nlm_opamp.h"
62#include "macro/nlm_other.h"
63
64#include "analog/nld_bjt.h"
65#include "analog/nld_fourterm.h"
66#include "analog/nld_switches.h"
67#include "analog/nld_twoterm.h"
68#include "analog/nld_opamps.h"
69#include "solver/nld_solver.h"
70
71#include "nld_legacy.h"
72
73NETLIST_EXTERNAL(diode_models)
74NETLIST_EXTERNAL(bjt_models)
75NETLIST_EXTERNAL(family_models)
76
77namespace netlist {
78   void initialize_factory(netlist::factory_list_t &factory);
79}
80
81#endif
trunk/src/lib/netlist/devices/nld_4020.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_4020.c
5 *
6 */
7
8#include "nld_4020.h"
9
10NETLIB_NAMESPACE_DEVICES_START()
11
12NETLIB_START(CD4020)
13{
14   register_sub("sub", sub);
15   register_sub("supply", m_supply);
16
17   register_input("RESET", m_RESET);
18   register_subalias("IP", sub.m_IP);
19   register_subalias("Q1", sub.m_Q[0]);
20   register_subalias("Q4", sub.m_Q[3]);
21   register_subalias("Q5", sub.m_Q[4]);
22   register_subalias("Q6", sub.m_Q[5]);
23   register_subalias("Q7", sub.m_Q[6]);
24   register_subalias("Q8", sub.m_Q[7]);
25   register_subalias("Q9", sub.m_Q[8]);
26   register_subalias("Q10", sub.m_Q[9]);
27   register_subalias("Q11", sub.m_Q[10]);
28   register_subalias("Q12", sub.m_Q[11]);
29   register_subalias("Q13", sub.m_Q[12]);
30   register_subalias("Q14", sub.m_Q[13]);
31   register_subalias("VDD", m_supply.m_vdd);
32   register_subalias("VSS", m_supply.m_vss);
33}
34
35NETLIB_RESET(CD4020)
36{
37   sub.do_reset();
38}
39
40
41NETLIB_START(CD4020_sub)
42{
43   register_input("IP", m_IP);
44
45   register_output("Q1", m_Q[0]);
46   register_output("Q4", m_Q[3]);
47   register_output("Q5", m_Q[4]);
48   register_output("Q6", m_Q[5]);
49   register_output("Q7", m_Q[6]);
50   register_output("Q8", m_Q[7]);
51   register_output("Q9", m_Q[8]);
52   register_output("Q10", m_Q[9]);
53   register_output("Q11", m_Q[10]);
54   register_output("Q12", m_Q[11]);
55   register_output("Q13", m_Q[12]);
56   register_output("Q14", m_Q[13]);
57
58   save(NLNAME(m_cnt));
59}
60
61NETLIB_RESET(CD4020_sub)
62{
63   m_IP.set_state(logic_t::STATE_INP_HL);
64   m_cnt = 0;
65}
66
67NETLIB_UPDATE(CD4020_sub)
68{
69   UINT8 cnt = m_cnt;
70   cnt = ( cnt + 1) & 0x3fff;
71   update_outputs(cnt);
72   m_cnt = cnt;
73}
74
75NETLIB_UPDATE(CD4020)
76{
77   if (INPLOGIC(m_RESET))
78   {
79      sub.m_cnt = 0;
80      sub.m_IP.inactivate();
81      /* static */ const netlist_time reset_time = netlist_time::from_nsec(140);
82      OUTLOGIC(sub.m_Q[0], 0, reset_time);
83      for (int i=3; i<14; i++)
84         OUTLOGIC(sub.m_Q[i], 0, reset_time);
85   }
86   else
87      sub.m_IP.activate_hl();
88}
89
90inline NETLIB_FUNC_VOID(CD4020_sub, update_outputs, (const UINT16 cnt))
91{
92   /* static */ const netlist_time out_delayQn[14] = {
93         NLTIME_FROM_NS(180), NLTIME_FROM_NS(280),
94         NLTIME_FROM_NS(380), NLTIME_FROM_NS(480),
95         NLTIME_FROM_NS(580), NLTIME_FROM_NS(680),
96         NLTIME_FROM_NS(780), NLTIME_FROM_NS(880),
97         NLTIME_FROM_NS(980), NLTIME_FROM_NS(1080),
98         NLTIME_FROM_NS(1180), NLTIME_FROM_NS(1280),
99         NLTIME_FROM_NS(1380), NLTIME_FROM_NS(1480),
100   };
101
102   OUTLOGIC(m_Q[0], 0, out_delayQn[0]);
103   for (int i=3; i<14; i++)
104      OUTLOGIC(m_Q[i], (cnt >> i) & 1, out_delayQn[i]);
105}
106
107NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_4020.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_4020.h
5 *
6 *  CD4020: 14-Stage Ripple Carry Binary Counters
7 *
8 *          +--------------+
9 *      Q12 |1     ++    16| VDD
10 *      Q13 |2           15| Q11
11 *      Q14 |3           14| Q10
12 *       Q6 |4    4020   13| Q8
13 *       Q5 |5           12| Q9
14 *       Q7 |6           11| RESET
15 *       Q4 |7           10| IP (Input pulses)
16 *      VSS |8            9| Q1
17 *          +--------------+
18 *
19 *
20 *  Naming conventions follow Texas Instruments datasheet
21 *
22 *  FIXME: Timing depends on VDD-VSS
23 *         This needs a cmos d-a/a-d proxy implementation.
24 *
25 */
26
27#ifndef NLD_4020_H_
28#define NLD_4020_H_
29
30#include "nl_base.h"
31#include "nld_cmos.h"
32
33/* FIXME: only used in mario.c */
34#define CD4020_WI(_name, _IP, _RESET, _VDD, _VSS)                              \
35      NET_REGISTER_DEV(CD4020_WI, _name)                                        \
36      NET_CONNECT(_name, IP, _IP)                                            \
37      NET_CONNECT(_name, RESET,  _RESET)                                     \
38      NET_CONNECT(_name, VDD,  _VDD)                                         \
39      NET_CONNECT(_name, VSS,  _VSS)
40
41#define CD4020(_name)                                                          \
42      NET_REGISTER_DEV(CD4020, _name)
43
44NETLIB_NAMESPACE_DEVICES_START()
45
46NETLIB_SUBDEVICE(CD4020_sub,
47
48   NETLIB_LOGIC_FAMILY(CD4XXX)
49   ATTR_HOT void update_outputs(const UINT16 cnt);
50
51   logic_input_t m_IP;
52
53   UINT16 m_cnt;
54
55   logic_output_t m_Q[14];
56);
57
58NETLIB_DEVICE(CD4020,
59   NETLIB_LOGIC_FAMILY(CD4XXX)
60   NETLIB_NAME(CD4020_sub) sub;
61   NETLIB_NAME(vdd_vss) m_supply;
62   logic_input_t m_RESET;
63);
64
65NETLIB_NAMESPACE_DEVICES_END()
66
67#endif /* NLD_4020_H_ */
trunk/src/lib/netlist/devices/nld_4066.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_4066.c
5 *
6 */
7
8#include "nld_4066.h"
9
10NETLIB_NAMESPACE_DEVICES_START()
11
12NETLIB_START(CD4066_GATE)
13{
14   register_input("CTL", m_control);
15   register_sub("PS", m_supply);
16   register_sub("R", m_R);
17   register_param("BASER", m_base_r, 270.0);
18}
19
20NETLIB_RESET(CD4066_GATE)
21{
22   m_R.do_reset();
23}
24
25NETLIB_UPDATE(CD4066_GATE)
26{
27   nl_double sup = (m_supply.vdd() - m_supply.vss());
28   nl_double low = NL_FCONST(0.45) * sup;
29   nl_double high = NL_FCONST(0.55) * sup;
30   nl_double in = INPANALOG(m_control) - m_supply.vss();
31   nl_double rON = m_base_r * NL_FCONST(5.0) / sup;
32   nl_double R = -1.0;
33
34   if (in < low)
35   {
36      R = NL_FCONST(1.0) / netlist().gmin();
37   }
38   else if (in > high)
39   {
40      R = rON;
41   }
42   if (R > NL_FCONST(0.0))
43   {
44      // We only need to update the net first if this is a time stepping net
45      if (1) // m_R.m_P.net().as_analog().solver()->is_timestep())
46      {
47         m_R.update_dev();
48         m_R.set_R(R);
49         m_R.m_P.schedule_after(NLTIME_FROM_NS(1));
50      }
51      else
52      {
53         m_R.set_R(R);
54         m_R.update_dev();
55      }
56   }
57}
58
59
60NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_4066.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_4066.h
5 *
6 *  CD4066: Quad Bilateral Switch
7 *
8 *          +--------------+
9 *   INOUTA |1     ++    14| VDD
10 *   OUTINA |2           13| CONTROLA
11 *   OUTINB |3           12| CONTROLD
12 *   INOUTB |4    4066   11| INOUTD
13 * CONTROLB |5           10| OUTIND
14 * CONTROLC |6            9| OUTINC
15 *      VSS |7            8| INOUTC
16 *          +--------------+
17 *
18 *  FIXME: These devices are slow (~125 ns). THis is currently not reflected
19 *
20 *  Naming conventions follow National semiconductor datasheet
21 *
22 */
23
24#ifndef NLD_4066_H_
25#define NLD_4066_H_
26
27#include "nl_base.h"
28#include "nld_cmos.h"
29
30#define CD4066_GATE(_name)                                                     \
31      NET_REGISTER_DEV(CD4066_GATE, _name)
32
33NETLIB_NAMESPACE_DEVICES_START()
34
35NETLIB_DEVICE(CD4066_GATE,
36   NETLIB_LOGIC_FAMILY(CD4XXX)
37public:
38
39   analog_input_t m_control;
40   NETLIB_NAME(R) m_R;
41
42   NETLIB_NAME(vdd_vss) m_supply;
43   param_double_t m_base_r;
44);
45
46NETLIB_NAMESPACE_DEVICES_END()
47
48#endif /* NLD_4066_H_ */
trunk/src/lib/netlist/devices/nld_7400.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7400.c
5 *
6 */
7
8#include "nld_7400.h"
9
10NETLIB_NAMESPACE_DEVICES_START()
11
12#if (USE_TRUTHTABLE)
13nld_7400::truthtable_t nld_7400::m_ttbl;
14const char *nld_7400::m_desc[] = {
15      "A , B | Q ",
16      "0,X|1|22",
17      "X,0|1|22",
18      "1,1|0|15",
19      ""
20};
21
22#endif
23
24NETLIB_START(7400_dip)
25{
26   register_sub("1", m_1);
27   register_sub("2", m_2);
28   register_sub("3", m_3);
29   register_sub("4", m_4);
30
31   register_subalias("1", m_1.m_I[0]);
32   register_subalias("2", m_1.m_I[1]);
33   register_subalias("3", m_1.m_Q[0]);
34
35   register_subalias("4", m_2.m_I[0]);
36   register_subalias("5", m_2.m_I[1]);
37   register_subalias("6", m_2.m_Q[0]);
38
39   register_subalias("9", m_3.m_I[0]);
40   register_subalias("10", m_3.m_I[1]);
41   register_subalias("8", m_3.m_Q[0]);
42
43   register_subalias("12", m_4.m_I[0]);
44   register_subalias("13", m_4.m_I[1]);
45   register_subalias("11", m_4.m_Q[0]);
46}
47
48NETLIB_UPDATE(7400_dip)
49{
50   /* only called during startup */
51   m_1.update_dev();
52   m_2.update_dev();
53   m_3.update_dev();
54   m_4.update_dev();
55}
56
57NETLIB_RESET(7400_dip)
58{
59   m_1.do_reset();
60   m_2.do_reset();
61   m_3.do_reset();
62   m_4.do_reset();
63}
64
65NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_7400.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7400.h
5 *
6 *  DM7400: Quad 2-Input NAND Gates
7 *
8 *          +--------------+
9 *       A1 |1     ++    14| VCC
10 *       B1 |2           13| B4
11 *       Y1 |3           12| A4
12 *       A2 |4    7400   11| Y4
13 *       B2 |5           10| B3
14 *       Y2 |6            9| A3
15 *      GND |7            8| Y3
16 *          +--------------+
17 *                  __
18 *              Y = AB
19 *          +---+---++---+
20 *          | A | B || Y |
21 *          +===+===++===+
22 *          | 0 | 0 || 1 |
23 *          | 0 | 1 || 1 |
24 *          | 1 | 0 || 1 |
25 *          | 1 | 1 || 0 |
26 *          +---+---++---+
27 *
28 *  Naming conventions follow National Semiconductor datasheet
29 *
30 */
31
32#ifndef NLD_7400_H_
33#define NLD_7400_H_
34
35#include "nld_signal.h"
36#include "nld_truthtable.h"
37
38#define TTL_7400_NAND(_name, _A, _B)                                                \
39      NET_REGISTER_DEV(TTL_7400_NAND, _name)                                               \
40      NET_CONNECT(_name, A, _A)                                                   \
41      NET_CONNECT(_name, B, _B)
42
43#define TTL_7400_DIP(_name)                                                         \
44      NET_REGISTER_DEV(TTL_7400_DIP, _name)
45
46NETLIB_NAMESPACE_DEVICES_START()
47
48#if (USE_TRUTHTABLE)
49NETLIB_TRUTHTABLE(7400, 2, 1, 0);
50#else
51NETLIB_SIGNAL(7400, 2, 0, 0);
52#endif
53
54NETLIB_DEVICE(7400_dip,
55
56   NETLIB_NAME(7400) m_1;
57   NETLIB_NAME(7400) m_2;
58   NETLIB_NAME(7400) m_3;
59   NETLIB_NAME(7400) m_4;
60);
61
62NETLIB_NAMESPACE_DEVICES_END()
63
64#endif /* NLD_7400_H_ */
trunk/src/lib/netlist/devices/nld_7402.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7402.c
5 *
6 */
7
8#include "nld_7402.h"
9
10NETLIB_NAMESPACE_DEVICES_START()
11
12#if (USE_TRUTHTABLE)
13nld_7402::truthtable_t nld_7402::m_ttbl;
14const char *nld_7402::m_desc[] = {
15      "A , B | Q ",
16      "0,0|1|22",
17      "X,1|0|15",
18      "1,X|0|15",
19      ""
20};
21
22#endif
23
24NETLIB_START(7402_dip)
25{
26   register_sub("1", m_1);
27   register_sub("2", m_2);
28   register_sub("3", m_3);
29   register_sub("4", m_4);
30
31   register_subalias("1", m_1.m_Q[0]);
32   register_subalias("2", m_1.m_I[0]);
33   register_subalias("3", m_1.m_I[1]);
34
35   register_subalias("4", m_2.m_Q[0]);
36   register_subalias("5", m_2.m_I[0]);
37   register_subalias("6", m_2.m_I[1]);
38
39   register_subalias("8", m_3.m_I[0]);
40   register_subalias("9", m_3.m_I[1]);
41   register_subalias("10", m_3.m_Q[0]);
42
43   register_subalias("11", m_4.m_I[0]);
44   register_subalias("12", m_4.m_I[1]);
45   register_subalias("13", m_4.m_Q[0]);
46}
47
48NETLIB_UPDATE(7402_dip)
49{
50   /* only called during startup */
51   m_1.update_dev();
52   m_2.update_dev();
53   m_3.update_dev();
54   m_4.update_dev();
55}
56
57NETLIB_RESET(7402_dip)
58{
59   m_1.do_reset();
60   m_2.do_reset();
61   m_3.do_reset();
62   m_4.do_reset();
63}
64
65NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_7402.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7402.h
5 *
6 *  DM7402: Quad 2-Input NOR Gates
7 *
8 *          +--------------+
9 *       Y1 |1     ++    14| VCC
10 *       A1 |2           13| Y4
11 *       B1 |3           12| B4
12 *       Y2 |4    7402   11| A4
13 *       A2 |5           10| Y3
14 *       B2 |6            9| B3
15 *      GND |7            8| A3
16 *          +--------------+
17 *                  ___
18 *              Y = A+B
19 *          +---+---++---+
20 *          | A | B || Y |
21 *          +===+===++===+
22 *          | 0 | 0 || 1 |
23 *          | 0 | 1 || 0 |
24 *          | 1 | 0 || 0 |
25 *          | 1 | 1 || 0 |
26 *          +---+---++---+
27 *
28 *  Naming conventions follow National Semiconductor datasheet
29 *
30 */
31
32#ifndef NLD_7402_H_
33#define NLD_7402_H_
34
35#include "nld_signal.h"
36#include "nld_truthtable.h"
37
38#define TTL_7402_NOR(_name, _I1, _I2)                                               \
39      NET_REGISTER_DEV(TTL_7402_NOR, _name)                                               \
40      NET_CONNECT(_name, A, _I1)                                                  \
41      NET_CONNECT(_name, B, _I2)
42
43#define TTL_7402_DIP(_name)                                                         \
44      NET_REGISTER_DEV(TTL_7402_DIP, _name)
45
46
47NETLIB_NAMESPACE_DEVICES_START()
48
49#if (USE_TRUTHTABLE)
50NETLIB_TRUTHTABLE(7402, 2, 1, 0);
51#else
52NETLIB_SIGNAL(7402, 2, 1, 0);
53#endif
54
55NETLIB_DEVICE(7402_dip,
56
57   NETLIB_NAME(7402) m_1;
58   NETLIB_NAME(7402) m_2;
59   NETLIB_NAME(7402) m_3;
60   NETLIB_NAME(7402) m_4;
61);
62
63NETLIB_NAMESPACE_DEVICES_END()
64
65#endif /* NLD_7402_H_ */
trunk/src/lib/netlist/devices/nld_7404.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7404.c
5 *
6 */
7
8#include "nld_7404.h"
9
10NETLIB_NAMESPACE_DEVICES_START()
11
12#if 1 && (USE_TRUTHTABLE)
13nld_7404::truthtable_t nld_7404::m_ttbl;
14const char *nld_7404::m_desc[] = {
15      "A | Q ",
16      "0 | 1|22",
17      "1 | 0|15",
18      ""
19};
20#else
21
22NETLIB_START(7404)
23{
24   register_input("A", m_I[0]);
25   register_output("Q", m_Q[0]);
26}
27
28NETLIB_RESET(7404)
29{
30}
31
32NETLIB_UPDATE(7404)
33{
34   /* static */ const netlist_time delay[2] = { NLTIME_FROM_NS(15), NLTIME_FROM_NS(22) };
35   UINT8 t = (INPLOGIC(m_I[0])) ^ 1;
36   OUTLOGIC(m_Q[0], t, delay[t]);
37}
38#endif
39
40NETLIB_START(7404_dip)
41{
42   register_sub("1", m_1);
43   register_sub("2", m_2);
44   register_sub("3", m_3);
45   register_sub("4", m_4);
46   register_sub("5", m_5);
47   register_sub("6", m_6);
48
49   register_subalias("1", m_1.m_I[0]);
50   register_subalias("2", m_1.m_Q[0]);
51
52   register_subalias("3", m_2.m_I[0]);
53   register_subalias("4", m_2.m_Q[0]);
54
55   register_subalias("5", m_3.m_I[0]);
56   register_subalias("6", m_3.m_Q[0]);
57
58   register_subalias("8", m_4.m_Q[0]);
59   register_subalias("9", m_4.m_I[0]);
60
61   register_subalias("10", m_5.m_Q[0]);
62   register_subalias("11", m_5.m_I[0]);
63
64   register_subalias("12", m_6.m_Q[0]);
65   register_subalias("13", m_6.m_I[0]);
66}
67
68NETLIB_UPDATE(7404_dip)
69{
70   /* only called during startup */
71
72   m_1.update_dev();
73   m_2.update_dev();
74   m_3.update_dev();
75   m_4.update_dev();
76   m_5.update_dev();
77   m_6.update_dev();
78}
79
80NETLIB_RESET(7404_dip)
81{
82   m_1.do_reset();
83   m_2.do_reset();
84   m_3.do_reset();
85   m_4.do_reset();
86   m_5.do_reset();
87   m_6.do_reset();
88}
89
90NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_7404.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7404.h
5 *
6 *  DM7404: Hex Inverting Gates
7 *
8 *          +--------------+
9 *       A1 |1     ++    14| VCC
10 *       Y1 |2           13| A6
11 *       A2 |3           12| Y6
12 *       Y2 |4    7404   11| A5
13 *       A3 |5           10| Y5
14 *       Y3 |6            9| A4
15 *      GND |7            8| Y4
16 *          +--------------+
17 *                 _
18 *             Y = A
19 *          +---++---+
20 *          | A || Y |
21 *          +===++===+
22 *          | 0 || 1 |
23 *          | 1 || 0 |
24 *          +---++---+
25 *
26 *  Naming conventions follow National Semiconductor datasheet
27 *
28 */
29
30#ifndef NLD_7404_H_
31#define NLD_7404_H_
32
33#include "nld_signal.h"
34#include "nld_truthtable.h"
35
36#define TTL_7404_INVERT(_name, _A)                                                  \
37      NET_REGISTER_DEV(TTL_7404_INVERT, _name)                                               \
38      NET_CONNECT(_name, A, _A)
39
40#define TTL_7404_DIP(_name)                                                         \
41      NET_REGISTER_DEV(TTL_7404_DIP, _name)
42
43NETLIB_NAMESPACE_DEVICES_START()
44
45#if 1 && (USE_TRUTHTABLE)
46NETLIB_TRUTHTABLE(7404, 1, 1, 0);
47#else
48NETLIB_DEVICE(7404,
49public:
50   netlist_logic_input_t m_I[1];
51   netlist_logic_output_t m_Q[1];
52);
53#endif
54
55NETLIB_DEVICE(7404_dip,
56
57   NETLIB_NAME(7404) m_1;
58   NETLIB_NAME(7404) m_2;
59   NETLIB_NAME(7404) m_3;
60   NETLIB_NAME(7404) m_4;
61   NETLIB_NAME(7404) m_5;
62   NETLIB_NAME(7404) m_6;
63);
64
65NETLIB_NAMESPACE_DEVICES_END()
66
67#endif /* NLD_7404_H_ */
trunk/src/lib/netlist/devices/nld_7408.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7408.c
5 *
6 */
7
8#include "nld_7408.h"
9
10NETLIB_NAMESPACE_DEVICES_START()
11
12#if (USE_TRUTHTABLE)
13nld_7408::truthtable_t nld_7408::m_ttbl;
14const char *nld_7408::m_desc[] = {
15      "A , B | Q ",
16      "X,0|0|15",
17      "0,X|0|15",
18      "1,1|1|22",
19      ""
20};
21
22#endif
23
24NETLIB_START(7408_dip)
25{
26   register_sub("1", m_1);
27   register_sub("2", m_2);
28   register_sub("3", m_3);
29   register_sub("4", m_4);
30
31   register_subalias("1", m_1.m_I[0]);
32   register_subalias("2", m_1.m_I[1]);
33   register_subalias("3", m_1.m_Q[0]);
34
35   register_subalias("4", m_2.m_I[0]);
36   register_subalias("5", m_2.m_I[1]);
37   register_subalias("6", m_2.m_Q[0]);
38
39   register_subalias("9", m_3.m_I[0]);
40   register_subalias("10", m_3.m_I[1]);
41   register_subalias("8", m_3.m_Q[0]);
42
43   register_subalias("12", m_4.m_I[0]);
44   register_subalias("13", m_4.m_I[1]);
45   register_subalias("11", m_4.m_Q[0]);
46}
47
48NETLIB_UPDATE(7408_dip)
49{
50   /* only called during startup */
51   m_1.update_dev();
52   m_2.update_dev();
53   m_3.update_dev();
54   m_4.update_dev();
55}
56
57NETLIB_RESET(7408_dip)
58{
59   m_1.do_reset();
60   m_2.do_reset();
61   m_3.do_reset();
62   m_4.do_reset();
63}
64
65NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_7408.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7408.h
5 *
6 *  DM7408: Quad 2-Input AND Gates
7 *
8 *          +--------------+
9 *       A1 |1     ++    14| VCC
10 *       B1 |2           13| B4
11 *       Y1 |3           12| A4
12 *       A2 |4    7408   11| Y4
13 *       B2 |5           10| B3
14 *       Y2 |6            9| A3
15 *      GND |7            8| Y3
16 *          +--------------+
17 *                  __
18 *              Y = AB
19 *          +---+---++---+
20 *          | A | B || Y |
21 *          +===+===++===+
22 *          | 0 | 0 || 0 |
23 *          | 0 | 1 || 0 |
24 *          | 1 | 0 || 0 |
25 *          | 1 | 1 || 1 |
26 *          +---+---++---+
27 *
28 *  Naming conventions follow Fairchild Semiconductor datasheet
29 *
30 */
31
32#ifndef NLD_7408_H_
33#define NLD_7408_H_
34
35#include "nld_signal.h"
36#include "nld_truthtable.h"
37
38#define TTL_7408_AND(_name, _A, _B)                                                 \
39      NET_REGISTER_DEV(TTL_7408_AND, _name)                                               \
40      NET_CONNECT(_name, A, _A)                                                   \
41      NET_CONNECT(_name, B, _B)
42
43#define TTL_7408_DIP(_name)                                                         \
44      NET_REGISTER_DEV(TTL_7408_DIP, _name)
45
46NETLIB_NAMESPACE_DEVICES_START()
47
48#if (USE_TRUTHTABLE)
49NETLIB_TRUTHTABLE(7408, 2, 1, 0);
50#else
51NETLIB_SIGNAL(7408, 2, 0, 1);
52#endif
53
54
55NETLIB_DEVICE(7408_dip,
56
57   NETLIB_NAME(7408) m_1;
58   NETLIB_NAME(7408) m_2;
59   NETLIB_NAME(7408) m_3;
60   NETLIB_NAME(7408) m_4;
61);
62
63NETLIB_NAMESPACE_DEVICES_END()
64
65#endif /* NLD_7408_H_ */
trunk/src/lib/netlist/devices/nld_7410.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7410.c
5 *
6 */
7
8#include "nld_7410.h"
9
10NETLIB_NAMESPACE_DEVICES_START()
11
12#if (USE_TRUTHTABLE)
13nld_7410::truthtable_t nld_7410::m_ttbl;
14const char *nld_7410::m_desc[] = {
15      "A,B,C|Q",
16      "0,X,X|1|22",
17      "X,0,X|1|22",
18      "X,X,0|1|22",
19      "1,1,1|0|15",
20      ""
21};
22
23#endif
24
25
26NETLIB_START(7410_dip)
27{
28   register_sub("1", m_1);
29   register_sub("2", m_2);
30   register_sub("3", m_3);
31
32   register_subalias("1", m_1.m_I[0]);
33   register_subalias("2", m_1.m_I[1]);
34   register_subalias("3", m_2.m_I[0]);
35   register_subalias("4", m_2.m_I[1]);
36   register_subalias("5", m_2.m_I[2]);
37   register_subalias("6", m_2.m_Q[0]);
38
39   register_subalias("8", m_3.m_Q[0]);
40   register_subalias("9", m_3.m_I[0]);
41   register_subalias("10", m_3.m_I[1]);
42   register_subalias("11", m_3.m_I[2]);
43
44   register_subalias("12", m_1.m_Q[0]);
45   register_subalias("13", m_1.m_I[2]);
46}
47
48NETLIB_UPDATE(7410_dip)
49{
50   /* only called during startup */
51   m_1.update_dev();
52   m_2.update_dev();
53   m_3.update_dev();
54}
55
56NETLIB_RESET(7410_dip)
57{
58   m_1.do_reset();
59   m_2.do_reset();
60   m_3.do_reset();
61}
62
63NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_7410.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7410.h
5 *
6 *  DM7410: Triple 3-Input NAND Gates
7 *
8 *          +--------------+
9 *       A1 |1     ++    14| VCC
10 *       B1 |2           13| C1
11 *       A2 |3           12| Y1
12 *       B2 |4    7410   11| C3
13 *       C2 |5           10| B3
14 *       Y2 |6            9| A3
15 *      GND |7            8| Y3
16 *          +--------------+
17 *                  ___
18 *              Y = ABC
19 *          +---+---+---++---+
20 *          | A | B | C || Y |
21 *          +===+===+===++===+
22 *          | X | X | 0 || 1 |
23 *          | X | 0 | X || 1 |
24 *          | 0 | X | X || 1 |
25 *          | 1 | 1 | 1 || 0 |
26 *          +---+---+---++---+
27 *
28 *  Naming conventions follow National Semiconductor datasheet
29 *
30 */
31
32#ifndef NLD_7410_H_
33#define NLD_7410_H_
34
35#include "nld_signal.h"
36#include "nld_truthtable.h"
37
38#define TTL_7410_NAND(_name, _I1, _I2, _I3)                                         \
39      NET_REGISTER_DEV(TTL_7410_NAND, _name)                                               \
40      NET_CONNECT(_name, A, _I1)                                                  \
41      NET_CONNECT(_name, B, _I2)                                                  \
42      NET_CONNECT(_name, C, _I3)
43
44#define TTL_7410_DIP(_name)                                                         \
45      NET_REGISTER_DEV(TTL_7410_DIP, _name)
46
47NETLIB_NAMESPACE_DEVICES_START()
48
49#if (USE_TRUTHTABLE)
50NETLIB_TRUTHTABLE(7410, 3, 1, 0);
51#else
52NETLIB_SIGNAL(7410, 3, 0, 0);
53#endif
54
55NETLIB_DEVICE(7410_dip,
56
57   NETLIB_NAME(7410) m_1;
58   NETLIB_NAME(7410) m_2;
59   NETLIB_NAME(7410) m_3;
60);
61
62NETLIB_NAMESPACE_DEVICES_END()
63
64#endif /* NLD_7410_H_ */
trunk/src/lib/netlist/devices/nld_74107.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_74107.c
5 *
6 */
7
8#include "nld_74107.h"
9
10NETLIB_NAMESPACE_DEVICES_START()
11
12NETLIB_START(74107Asub)
13{
14   register_input("CLK", m_clk);
15   register_output("Q", m_Q);
16   register_output("QQ", m_QQ);
17
18   save(NLNAME(m_Q1));
19   save(NLNAME(m_Q2));
20   save(NLNAME(m_F));
21}
22
23NETLIB_RESET(74107Asub)
24{
25   m_clk.set_state(logic_t::STATE_INP_HL);
26   m_Q.initial(0);
27   m_QQ.initial(1);
28
29   m_Q1 = 0;
30   m_Q2 = 0;
31   m_F = 0;
32}
33
34NETLIB_START(74107A)
35{
36   register_sub("sub", sub);
37
38   register_subalias("CLK", sub.m_clk);
39   register_input("J", m_J);
40   register_input("K", m_K);
41   register_input("CLRQ", m_clrQ);
42   register_subalias("Q", sub.m_Q);
43   register_subalias("QQ", sub.m_QQ);
44
45}
46
47NETLIB_RESET(74107A)
48{
49   sub.reset();
50}
51
52ATTR_HOT inline void NETLIB_NAME(74107Asub)::newstate(const netlist_sig_t state)
53{
54   const netlist_time delay[2] = { NLTIME_FROM_NS(25), NLTIME_FROM_NS(40) };
55
56   OUTLOGIC(m_Q, state, delay[state]);
57   OUTLOGIC(m_QQ, state ^ 1, delay[state ^ 1]);
58}
59
60NETLIB_UPDATE(74107Asub)
61{
62   const netlist_sig_t t = m_Q.net().as_logic().Q();
63   newstate(((t ^ 1) & m_Q1) | (t & m_Q2) | m_F);
64   if (m_Q1 ^ 1)
65      m_clk.inactivate();
66}
67
68NETLIB_UPDATE(74107A)
69{
70   const UINT8 JK = (INPLOGIC(m_J) << 1) | INPLOGIC(m_K);
71
72   switch (JK)
73   {
74      case 0:
75         sub.m_Q1 = 0;
76         sub.m_Q2 = 1;
77         sub.m_F  = 0;
78         sub.m_clk.inactivate();
79         break;
80      case 1:             // (!INPLOGIC(m_J) & INPLOGIC(m_K))
81         sub.m_Q1 = 0;
82         sub.m_Q2 = 0;
83         sub.m_F  = 0;
84         break;
85      case 2:             // (INPLOGIC(m_J) & !INPLOGIC(m_K))
86         sub.m_Q1 = 0;
87         sub.m_Q2 = 0;
88         sub.m_F  = 1;
89         break;
90      case 3:             // (INPLOGIC(m_J) & INPLOGIC(m_K))
91         sub.m_Q1 = 1;
92         sub.m_Q2 = 0;
93         sub.m_F  = 0;
94         break;
95      default:
96         break;
97   }
98
99   if (!INPLOGIC(m_clrQ))
100   {
101      sub.m_clk.inactivate();
102      sub.newstate(0);
103   }
104   else if (!sub.m_Q2)
105      sub.m_clk.activate_hl();
106}
107
108NETLIB_START(74107_dip)
109{
110   register_sub("1", m_1);
111   register_sub("2", m_2);
112
113   register_subalias("1", m_1.m_J);
114   register_subalias("2", m_1.sub.m_QQ);
115   register_subalias("3", m_1.sub.m_Q);
116
117   register_subalias("4", m_1.m_K);
118   register_subalias("5", m_2.sub.m_Q);
119   register_subalias("6", m_2.sub.m_QQ);
120
121   // register_subalias("7", ); ==> GND
122
123   register_subalias("8", m_2.m_J);
124   register_subalias("9", m_2.sub.m_clk);
125   register_subalias("10", m_2.m_clrQ);
126
127   register_subalias("11", m_2.m_K);
128   register_subalias("12", m_1.sub.m_clk);
129   register_subalias("13", m_1.m_clrQ);
130
131   // register_subalias("14", ); ==> VCC
132}
133
134NETLIB_RESET(74107_dip)
135{
136   m_1.do_reset();
137   m_2.do_reset();
138}
139
140NETLIB_UPDATE(74107_dip)
141{
142   /* only called during startup */
143   m_1.update_dev();
144   m_2.update_dev();
145}
146
147NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_74107.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_74107.h
5 *
6 *  DM74107: DUAL J-K FLIP-FLOPS WITH CLEAR
7 *
8 *          +--------------+
9 *       1J |1     ++    14| VCC
10 *      1QQ |2           13| 1CLRQ
11 *       1Q |3           12| 1CLK
12 *       1K |4    74107  11| 2K
13 *       2Q |5           10| 2CLRQ
14 *      2QQ |6            9| 2CLK
15 *      GND |7            8| 2J
16 *          +--------------+
17 *
18 *
19 *          Function table 107
20 *
21 *          +-----+-----+-----+---++---+-----+
22 *          | CLRQ| CLK |  J  | K || Q | QQ  |
23 *          +=====+=====+=====+===++===+=====+
24 *          |  0  |  X  |  X  | X || 0 |  1  |
25 *          |  1  |  *  |  0  | 0 || Q0| Q0Q |
26 *          |  1  |  *  |  1  | 0 || 1 |  0  |
27 *          |  1  |  *  |  0  | 1 || 0 |  1  |
28 *          |  1  |  *  |  1  | 1 || TOGGLE  |
29 *          +-----+-----+-----+---++---+-----+
30 *                _
31 *          * = _| |_
32 *
33 *          This is positive triggered, J and K
34 *          are latched during clock high and
35 *          transferred when CLK falls.
36 *
37 *          Function table 107A
38 *
39 *          +-----+-----+-----+---++---+-----+
40 *          | CLRQ| CLK |  J  | K || Q | QQ  |
41 *          +=====+=====+=====+===++===+=====+
42 *          |  0  |  X  |  X  | X || 0 |  1  |
43 *          |  1  |  F  |  0  | 0 || Q0| Q0Q |
44 *          |  1  |  F  |  1  | 0 || 1 |  0  |
45 *          |  1  |  F  |  0  | 1 || 0 |  1  |
46 *          |  1  |  F  |  1  | 1 || TOGGLE  |
47 *          |  1  |  1  |  X  | X || Q0| Q0Q |
48 *          +-----+-----+-----+---++---+-----+
49 *
50 *          THe 107A is negative triggered.
51 *
52 *  Naming conventions follow Texas instruments datasheet
53 *
54 *  FIXME: Currently, only the 107A is implemented.
55 *         The 107 uses the same model.
56 *
57 */
58
59#ifndef NLD_74107_H_
60#define NLD_74107_H_
61
62#include "nl_base.h"
63
64#define TTL_74107A(_name, _CLK, _J, _K, _CLRQ)                                      \
65      NET_REGISTER_DEV(TTL_74107A, _name)                                             \
66      NET_CONNECT(_name, CLK, _CLK)                                               \
67      NET_CONNECT(_name, J,  _J)                                                  \
68      NET_CONNECT(_name, K,  _K)                                                  \
69      NET_CONNECT(_name, CLRQ,  _CLRQ)
70
71#define TTL_74107(_name, _CLK, _J, _K, _CLRQ)                                       \
72      TTL_74107A(_name, _CLK, _J, _K, _CLRQ)
73
74#define TTL_74107_DIP(_name)                                                         \
75      NET_REGISTER_DEV(TTL_74107_DIP, _name)
76
77NETLIB_NAMESPACE_DEVICES_START()
78
79NETLIB_SUBDEVICE(74107Asub,
80   logic_input_t m_clk;
81
82   logic_output_t m_Q;
83   logic_output_t m_QQ;
84
85   netlist_sig_t m_Q1;
86   netlist_sig_t m_Q2;
87   netlist_sig_t m_F;
88
89   ATTR_HOT void newstate(const netlist_sig_t state);
90
91);
92
93NETLIB_DEVICE(74107A,
94public:
95   NETLIB_NAME(74107Asub) sub;
96
97   logic_input_t m_J;
98   logic_input_t m_K;
99   logic_input_t m_clrQ;
100
101);
102
103class NETLIB_NAME(74107) : public NETLIB_NAME(74107A)
104{
105public:
106   NETLIB_NAME(74107) ()
107   :   NETLIB_NAME(74107A) () {}
108
109};
110
111NETLIB_DEVICE(74107_dip,
112
113   NETLIB_NAME(74107) m_1;
114   NETLIB_NAME(74107) m_2;
115);
116
117NETLIB_NAMESPACE_DEVICES_END()
118
119#endif /* NLD_74107_H_ */
trunk/src/lib/netlist/devices/nld_7411.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7411.c
5 *
6 */
7
8#include "nld_7411.h"
9
10NETLIB_NAMESPACE_DEVICES_START()
11
12#if (USE_TRUTHTABLE)
13nld_7411::truthtable_t nld_7411::m_ttbl;
14const char *nld_7411::m_desc[] = {
15      "A,B,C|Q",
16      "0,X,X|0|15",
17      "X,0,X|0|15",
18      "X,X,0|0|15",
19      "1,1,1|1|22",
20      ""
21};
22#endif
23
24NETLIB_START(7411_dip)
25{
26   register_sub("1", m_1);
27   register_sub("2", m_2);
28   register_sub("3", m_3);
29
30   register_subalias("1", m_1.m_I[0]);
31   register_subalias("2", m_1.m_I[1]);
32   register_subalias("3", m_2.m_I[0]);
33   register_subalias("4", m_2.m_I[1]);
34   register_subalias("5", m_2.m_I[2]);
35   register_subalias("6", m_2.m_Q[0]);
36
37   register_subalias("8", m_3.m_Q[0]);
38   register_subalias("9", m_3.m_I[0]);
39   register_subalias("10", m_3.m_I[1]);
40   register_subalias("11", m_3.m_I[2]);
41
42   register_subalias("12", m_1.m_Q[0]);
43   register_subalias("13", m_1.m_I[2]);
44}
45
46NETLIB_UPDATE(7411_dip)
47{
48   /* only called during startup */
49   m_1.update_dev();
50   m_2.update_dev();
51   m_3.update_dev();
52}
53
54NETLIB_RESET(7411_dip)
55{
56   m_1.do_reset();
57   m_2.do_reset();
58   m_3.do_reset();
59}
60
61NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_7411.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7411.h
5 *
6 *  DM7411: Triple 3-Input AND Gates
7 *
8 *          +--------------+
9 *       A1 |1     ++    14| VCC
10 *       B1 |2           13| C1
11 *       A2 |3           12| Y1
12 *       B2 |4    7411   11| C3
13 *       C2 |5           10| B3
14 *       Y2 |6            9| A3
15 *      GND |7            8| Y3
16 *          +--------------+
17 *
18 *              Y = ABC
19 *          +---+---+---++---+
20 *          | A | B | C || Y |
21 *          +===+===+===++===+
22 *          | X | X | 0 || 0 |
23 *          | X | 0 | X || 0 |
24 *          | 0 | X | X || 0 |
25 *          | 1 | 1 | 1 || 1 |
26 *          +---+---+---++---+
27 *
28 *  Naming conventions follow National Semiconductor datasheet
29 *
30 */
31
32#ifndef NLD_7411_H_
33#define NLD_7411_H_
34
35#include "nld_signal.h"
36#include "nld_truthtable.h"
37
38#define TTL_7411_AND(_name, _I1, _I2, _I3)                                         \
39      NET_REGISTER_DEV(TTL_7411_AND, _name)                                               \
40      NET_CONNECT(_name, A, _I1)                                                  \
41      NET_CONNECT(_name, B, _I2)                                                  \
42      NET_CONNECT(_name, C, _I3)
43
44#define TTL_7411_DIP(_name)                                                         \
45      NET_REGISTER_DEV(TTL_7411_DIP, _name)
46
47NETLIB_NAMESPACE_DEVICES_START()
48
49#if (USE_TRUTHTABLE)
50NETLIB_TRUTHTABLE(7411, 3, 1, 0);
51#else
52NETLIB_SIGNAL(7411, 3, 0, 1);
53#endif
54
55
56NETLIB_DEVICE(7411_dip,
57
58   NETLIB_NAME(7411) m_1;
59   NETLIB_NAME(7411) m_2;
60   NETLIB_NAME(7411) m_3;
61);
62
63NETLIB_NAMESPACE_DEVICES_END()
64
65#endif /* NLD_7411_H_ */
trunk/src/lib/netlist/devices/nld_74123.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_74123.c
5 *
6 */
7
8#include "nld_74123.h"
9
10#define R_OFF (1E20)
11#define R_ON (m_RI.Value())
12
13NETLIB_NAMESPACE_DEVICES_START()
14
15NETLIB_START(74123)
16{
17   if ((m_dev_type != 9602) && (m_dev_type != 4538) )
18      m_dev_type = 74123;
19
20   register_sub("RP", m_RP);
21   register_sub("RN", m_RN);
22
23   register_input("A", m_A);
24   register_input("B", m_B);
25   register_input("CLRQ", m_CLRQ);
26   register_output("Q", m_Q);
27   register_output("QQ", m_QQ);
28
29   register_output("_RP_Q", m_RP_Q); // internal
30   register_output("_RN_Q", m_RN_Q); // internal
31
32   register_input("_CV", m_CV); // internal
33
34   register_subalias("GND", m_RN.m_R.m_N);
35   register_subalias("VCC", m_RP.m_R.m_P);
36   register_subalias("C",   m_RN.m_R.m_N);
37   register_subalias("RC",  m_RN.m_R.m_P);
38
39   if (m_dev_type == 4538)
40      register_param("K", m_K, 0.4);
41   else
42      register_param("K", m_K, 0.4);
43
44   register_param("RI", m_RI, 400.0); // around 250 for HC series, 400 on LS/TTL, estimated from datasheets
45
46   connect_late(m_RP_Q, m_RP.m_I);
47   connect_late(m_RN_Q, m_RN.m_I);
48
49   connect_late(m_RN.m_R.m_P, m_RP.m_R.m_N);
50   connect_late(m_CV, m_RN.m_R.m_P);
51
52   save(NLNAME(m_last_trig));
53   save(NLNAME(m_state));
54   save(NLNAME(m_KP));
55
56}
57
58NETLIB_UPDATE(74123)
59{
60   netlist_sig_t m_trig;
61   netlist_sig_t res = !INPLOGIC(m_CLRQ);
62   netlist_time t_AB_to_Q = NLTIME_FROM_NS(10);
63   netlist_time t_C_to_Q = NLTIME_FROM_NS(10);
64
65   if (m_dev_type == 74123)
66   {
67      m_trig = (INPLOGIC(m_A) ^ 1) & INPLOGIC(m_B) & INPLOGIC(m_CLRQ);
68   }
69   else if (m_dev_type == 9602)
70   {
71      m_trig = (INPLOGIC(m_A) ^ 1) | INPLOGIC(m_B);
72   }
73   else // 4538
74   {
75      m_trig = (INPLOGIC(m_B) ^ 1) | INPLOGIC(m_A);
76      // The line below is from the datasheet truthtable ... doesn't make sense at all
77      //res = res | INPLOGIC(m_A) | (INPLOGIC(m_B) ^ 1);
78      t_AB_to_Q = NLTIME_FROM_NS(300);
79      t_C_to_Q = NLTIME_FROM_NS(250);
80   }
81
82   if (res)
83   {
84      OUTLOGIC(m_Q, 0, t_C_to_Q);
85      OUTLOGIC(m_QQ, 1, t_C_to_Q);
86      /* quick charge until trigger */
87      /* FIXME: SGS datasheet shows quick charge to 5V,
88       * though schematics indicate quick charge to Vhigh only.
89       */
90      OUTLOGIC(m_RP_Q, 1, t_C_to_Q); // R_ON
91      OUTLOGIC(m_RN_Q, 0, t_C_to_Q); // R_OFF
92      m_state = 2; //charging (quick)
93   }
94   else if (!m_last_trig && m_trig)
95   {
96      // FIXME: Timing!
97      OUTLOGIC(m_Q, 1, t_AB_to_Q);
98      OUTLOGIC(m_QQ, 0,t_AB_to_Q);
99
100      OUTLOGIC(m_RN_Q, 1, t_AB_to_Q); // R_ON
101      OUTLOGIC(m_RP_Q, 0, t_AB_to_Q); // R_OFF
102
103      m_state = 1; // discharging
104   }
105
106   m_last_trig = m_trig;
107
108   if (m_state == 1)
109   {
110      const nl_double vLow = m_KP * TERMANALOG(m_RP.m_R.m_P);
111      if (INPANALOG(m_CV) < vLow)
112      {
113         OUTLOGIC(m_RN_Q, 0, NLTIME_FROM_NS(10)); // R_OFF
114         m_state = 2; // charging
115      }
116   }
117   if (m_state == 2)
118   {
119      const nl_double vHigh = TERMANALOG(m_RP.m_R.m_P) * (1.0 - m_KP);
120      if (INPANALOG(m_CV) > vHigh)
121      {
122         OUTLOGIC(m_RP_Q, 0, NLTIME_FROM_NS(10)); // R_OFF
123
124         OUTLOGIC(m_Q, 0, NLTIME_FROM_NS(10));
125         OUTLOGIC(m_QQ, 1, NLTIME_FROM_NS(10));
126         m_state = 0; // waiting
127      }
128   }
129}
130
131NETLIB_RESET(74123)
132{
133   m_KP = 1.0 / (1.0 + exp(m_K.Value()));
134
135   m_RP.do_reset();
136   m_RN.do_reset();
137
138   //m_RP.set_R(R_OFF);
139   //m_RN.set_R(R_OFF);
140
141   m_last_trig = 0;
142   m_state = 0;
143}
144
145NETLIB_START(74123_dip)
146{
147   register_sub("1", m_1);
148   register_sub("2", m_2);
149
150   register_subalias("1", m_1.m_A);
151   register_subalias("2", m_1.m_B);
152   register_subalias("3", m_1.m_CLRQ);
153   register_subalias("4", m_1.m_QQ);
154   register_subalias("5", m_2.m_Q);
155   register_subalias("6", m_2.m_RN.m_R.m_N);
156   register_subalias("7", m_2.m_RN.m_R.m_P);
157   register_subalias("8", m_1.m_RN.m_R.m_N);
158   connect_late(m_1.m_RN.m_R.m_N, m_2.m_RN.m_R.m_N);
159
160   register_subalias("9", m_2.m_A);
161   register_subalias("10", m_2.m_B);
162   register_subalias("11", m_2.m_CLRQ);
163   register_subalias("12", m_2.m_QQ);
164   register_subalias("13", m_1.m_Q);
165   register_subalias("14", m_1.m_RN.m_R.m_N);
166   register_subalias("15", m_1.m_RN.m_R.m_P);
167   register_subalias("16", m_1.m_RP.m_R.m_P);
168   connect_late(m_1.m_RP.m_R.m_P, m_2.m_RP.m_R.m_P);
169}
170
171NETLIB_UPDATE(74123_dip)
172{
173   /* only called during startup */
174   m_1.update_dev();
175   m_2.update_dev();
176}
177
178NETLIB_RESET(74123_dip)
179{
180   m_1.do_reset();
181   m_2.do_reset();
182}
183
184NETLIB_START(9602_dip)
185{
186   m_1.m_dev_type = 9602;
187   m_2.m_dev_type = 9602;
188
189   register_sub("1", m_1);
190   register_sub("2", m_2);
191
192   register_subalias("1", m_1.m_RN.m_R.m_N); // C1
193   register_subalias("2", m_1.m_RN.m_R.m_P); // RC1
194   register_subalias("3", m_1.m_CLRQ);
195   register_subalias("4", m_1.m_B);
196   register_subalias("5", m_1.m_A);
197   register_subalias("6", m_1.m_Q);
198   register_subalias("7", m_1.m_QQ);
199   register_subalias("8", m_1.m_RN.m_R.m_N);
200   connect_late(m_1.m_RN.m_R.m_N, m_2.m_RN.m_R.m_N);
201
202   register_subalias("9", m_2.m_QQ);
203   register_subalias("10", m_2.m_Q);
204   register_subalias("11", m_2.m_A);
205   register_subalias("12", m_2.m_B);
206   register_subalias("13", m_2.m_CLRQ);
207   register_subalias("14", m_2.m_RN.m_R.m_P); // RC2
208   register_subalias("15", m_2.m_RN.m_R.m_N); // C2
209   register_subalias("16", m_1.m_RP.m_R.m_P);
210   connect_late(m_1.m_RP.m_R.m_P, m_2.m_RP.m_R.m_P);
211}
212
213NETLIB_UPDATE(9602_dip)
214{
215   /* only called during startup */
216   m_1.update_dev();
217   m_2.update_dev();
218}
219
220NETLIB_RESET(9602_dip)
221{
222   m_1.do_reset();
223   m_2.do_reset();
224}
225
226NETLIB_START(4538_dip)
227{
228   m_1.m_dev_type = 4538;
229   m_2.m_dev_type = 4538;
230
231   register_sub("1", m_1);
232   register_sub("2", m_2);
233
234   register_subalias("1", m_1.m_RN.m_R.m_N); // C1
235   register_subalias("2", m_1.m_RN.m_R.m_P); // RC1
236   register_subalias("3", m_1.m_CLRQ);
237   register_subalias("4", m_1.m_A);
238   register_subalias("5", m_1.m_B);
239   register_subalias("6", m_1.m_Q);
240   register_subalias("7", m_1.m_QQ);
241   register_subalias("8", m_1.m_RN.m_R.m_N);
242   connect_late(m_1.m_RN.m_R.m_N, m_2.m_RN.m_R.m_N);
243
244   register_subalias("9", m_2.m_QQ);
245   register_subalias("10", m_2.m_Q);
246   register_subalias("11", m_2.m_B);
247   register_subalias("12", m_2.m_A);
248   register_subalias("13", m_2.m_CLRQ);
249   register_subalias("14", m_2.m_RN.m_R.m_P); // RC2
250   register_subalias("15", m_2.m_RN.m_R.m_N); // C2
251   register_subalias("16", m_1.m_RP.m_R.m_P);
252   connect_late(m_1.m_RP.m_R.m_P, m_2.m_RP.m_R.m_P);
253}
254
255NETLIB_UPDATE(4538_dip)
256{
257   /* only called during startup */
258   m_1.update_dev();
259   m_2.update_dev();
260}
261
262NETLIB_RESET(4538_dip)
263{
264   m_1.do_reset();
265   m_2.do_reset();
266}
267
268NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_74123.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_74123.h
5 *
6 *  74123: Dual Retriggerable One-Shot with Clear and Complementary Outputs
7 *
8 *           +--------------+
9 *        A1 |1     ++    16| VCC
10 *        B1 |2           15| RC1
11 *      CLR1 |3           14| C1
12 *       Q1Q |4   74123   13| Q1
13 *        Q2 |5           12| Q2Q
14 *        C2 |6           11| CLR2
15 *       RC2 |7           10| B2
16 *       GND |8            9| A2
17 *           +--------------+
18 *
19 *  Naming conventions follow Fairchild Semiconductor datasheet
20 *
21 *  DM9602: Dual Retriggerable, Resettable One Shots
22 *
23 *           +--------------+
24 *        C1 |1     ++    16| VCC
25 *       RC1 |2           15| C2
26 *      CLR1 |3           14| RC2
27 *        B1 |4    9602   13| CLR2
28 *        A1 |5           12| B2
29 *        Q1 |6           11| A2
30 *       Q1Q |7           10| Q2
31 *       GND |8            9| Q2Q
32 *           +--------------+
33 *
34 *  CD4538: Dual Retriggerable, Resettable One Shots
35 *
36 *           +--------------+
37 *        C1 |1     ++    16| VCC
38 *       RC1 |2           15| C2
39 *      CLR1 |3           14| RC2
40 *        A1 |4    4538   13| CLR2
41 *        B1 |5           12| A2
42 *        Q1 |6           11| B2
43 *       Q1Q |7           10| Q2
44 *       GND |8            9| Q2Q
45 *           +--------------+
46 *
47 */
48
49#ifndef NLD_74123_H_
50#define NLD_74123_H_
51
52#include "nl_base.h"
53#include "nld_system.h"
54#include "analog/nld_twoterm.h"
55
56#define TTL_74123(_name)                                                        \
57      NET_REGISTER_DEV(TTL_74123, _name)
58
59NETLIB_NAMESPACE_DEVICES_START()
60
61NETLIB_DEVICE(74123,
62public:
63   NETLIB_NAME(res_sw) m_RP;
64   NETLIB_NAME(res_sw) m_RN;
65
66   logic_output_t m_RP_Q;
67   logic_output_t m_RN_Q;
68
69   logic_input_t m_A;
70   logic_input_t m_B;
71   logic_input_t m_CLRQ;
72   logic_output_t m_Q;
73   logic_output_t m_QQ;
74
75   analog_input_t m_CV;
76
77   netlist_sig_t m_last_trig;
78   UINT8         m_state;
79   double        m_KP;
80
81   param_double_t m_K;
82   param_double_t m_RI;
83
84   int m_dev_type;
85);
86
87#define TTL_74123_DIP(_name)                                                         \
88      NET_REGISTER_DEV(TTL_74123_DIP, _name)
89
90NETLIB_DEVICE(74123_dip,
91
92   NETLIB_NAME(74123) m_1;
93   NETLIB_NAME(74123) m_2;
94
95);
96
97/* The 9602 is very similar to the 123. Input triggering is slightly different
98 * THe 9602 uses an OR gate instead of an AND gate.
99 */
100
101#define TTL_9602_DIP(_name)                                                         \
102      NET_REGISTER_DEV(TTL_9602_DIP, _name)
103
104NETLIB_DEVICE(9602_dip,
105
106   NETLIB_NAME(74123) m_1;
107   NETLIB_NAME(74123) m_2;
108
109);
110
111/*
112 * The CD4538 is pretty similar to the 9602
113 */
114
115#define CD4538_DIP(_name)                                                         \
116      NET_REGISTER_DEV(CD4538_DIP, _name)
117
118NETLIB_DEVICE(4538_dip,
119   NETLIB_LOGIC_FAMILY(CD4XXX)
120   NETLIB_NAME(74123) m_1;
121   NETLIB_NAME(74123) m_2;
122);
123
124NETLIB_NAMESPACE_DEVICES_END()
125
126
127#endif /* NLD_74123_H_ */
trunk/src/lib/netlist/devices/nld_74153.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_74153.c
5 *
6 */
7
8#include "nld_74153.h"
9
10NETLIB_NAMESPACE_DEVICES_START()
11
12/* FIXME: timing is not 100% accurate, Strobe and Select inputs have a
13 *        slightly longer timing.
14 *        Convert this to sub-devices at some time.
15 */
16
17NETLIB_START(74153sub)
18{
19   register_input("C0", m_C[0]);
20   register_input("C1", m_C[1]);
21   register_input("C2", m_C[2]);
22   register_input("C3", m_C[3]);
23   register_input("G", m_G);
24
25   register_output("AY", m_Y); //FIXME: Change netlists
26
27   m_chan = 0;
28
29   save(NLNAME(m_chan));
30}
31
32NETLIB_RESET(74153sub)
33{
34   m_chan = 0;
35}
36
37NETLIB_UPDATE(74153sub)
38{
39   const netlist_time delay[2] = { NLTIME_FROM_NS(23), NLTIME_FROM_NS(18) };
40   if (!INPLOGIC(m_G))
41   {
42      UINT8 t = INPLOGIC(m_C[m_chan]);
43      OUTLOGIC(m_Y, t, delay[t] );
44   }
45   else
46   {
47      OUTLOGIC(m_Y, 0, delay[0]);
48   }
49}
50
51
52NETLIB_START(74153)
53{
54   register_sub("sub", m_sub);
55
56   register_subalias("C0", m_sub.m_C[0]);
57   register_subalias("C1",  m_sub.m_C[1]);
58   register_subalias("C2",  m_sub.m_C[2]);
59   register_subalias("C3",  m_sub.m_C[3]);
60   register_input("A", m_A);
61   register_input("B", m_B);
62   register_subalias("G",  m_sub.m_G);
63
64   register_subalias("AY",  m_sub.m_Y); //FIXME: Change netlists
65}
66
67NETLIB_RESET(74153)
68{
69}
70
71
72
73NETLIB_UPDATE(74153)
74{
75   m_sub.m_chan = (INPLOGIC(m_A) | (INPLOGIC(m_B)<<1));
76   m_sub.update();
77}
78
79
80NETLIB_START(74153_dip)
81{
82   register_sub("1", m_1);
83   register_sub("2", m_2);
84
85   register_subalias("1", m_1.m_G);
86   register_input("2", m_B);    // m_2.m_B
87   register_subalias("3", m_1.m_C[3]);
88   register_subalias("4", m_1.m_C[2]);
89   register_subalias("5", m_1.m_C[1]);
90   register_subalias("6", m_1.m_C[0]);
91   register_subalias("7", m_1.m_Y);
92
93   register_subalias("9", m_2.m_Y);
94   register_subalias("10", m_2.m_C[0]);
95   register_subalias("11", m_2.m_C[1]);
96   register_subalias("12", m_2.m_C[2]);
97   register_subalias("13", m_2.m_C[3]);
98
99   register_input("14", m_A);   // m_2.m_B
100   register_subalias("15", m_2.m_G);
101}
102
103NETLIB_UPDATE(74153_dip)
104{
105   m_2.m_chan = m_1.m_chan = (INPLOGIC(m_A) | (INPLOGIC(m_B)<<1));
106   m_1.update();
107   m_2.update();
108}
109
110NETLIB_RESET(74153_dip)
111{
112   m_1.do_reset();
113   m_2.do_reset();
114}
115
116NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_74153.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_74153.h
5 *
6 *  DM74153: Dual 4-Line to 1-Line Data Selectors Multiplexers
7 *
8 *          +--------------+
9 *       G1 |1     ++    16| VCC
10 *        B |2           15| G2
11 *      1C3 |3           14| A
12 *      1C2 |4   74153   13| 2C3
13 *      1C1 |5           12| 2C2
14 *      1C0 |6           11| 2C1
15 *       Y1 |7           10| 2C0
16 *      GND |8            9| Y2
17 *          +--------------+
18 *
19 *
20 *          Function table
21 *
22 *          +-----+-----++----+----+----+----++----+----+
23 *          |  B  |  A  || C0 | C1 | C2 | C3 ||  G |  Y |
24 *          +=====+=====++====+====+====+====++====+====+
25 *          |  X  |  X  ||  X |  X |  X |  X ||  H |  L |
26 *          |  L  |  L  ||  L |  X |  X |  X ||  L |  L |
27 *          |  L  |  L  ||  H |  X |  X |  X ||  L |  H |
28 *          |  L  |  H  ||  X |  L |  X |  X ||  L |  L |
29 *          |  L  |  H  ||  X |  H |  X |  X ||  L |  H |
30 *          |  H  |  L  ||  X |  X |  L |  X ||  L |  L |
31 *          |  H  |  L  ||  X |  X |  H |  X ||  L |  H |
32 *          |  H  |  H  ||  X |  X |  X |  L ||  L |  L |
33 *          |  H  |  H  ||  X |  X |  X |  H ||  L |  H |
34 *          +-----+-----++----+----+----+----++----+----+
35 *
36 *  A, B : Select Inputs
37 *  C*   : Data inputs
38 *  G    : Strobe
39 *  Y    : Output
40 *
41 *  Naming conventions follow National Semiconductor datasheet
42 *
43 */
44
45#ifndef NLD_74153_H_
46#define NLD_74153_H_
47
48#include "nl_base.h"
49
50#define TTL_74153(_name, _C0, _C1, _C2, _C3, _A, _B, _G)                            \
51      NET_REGISTER_DEV(TTL_74153, _name)                                              \
52      NET_CONNECT(_name, C0, _C0)                                                 \
53      NET_CONNECT(_name, C1, _C1)                                                 \
54      NET_CONNECT(_name, C2, _C2)                                                 \
55      NET_CONNECT(_name, C3, _C3)                                                 \
56      NET_CONNECT(_name, A, _A)                                                   \
57      NET_CONNECT(_name, B, _B)                                                   \
58      NET_CONNECT(_name, G, _G)
59
60#define TTL_74153_DIP(_name)                                                         \
61      NET_REGISTER_DEV(TTL_74153_DIP, _name)
62
63NETLIB_NAMESPACE_DEVICES_START()
64
65NETLIB_SUBDEVICE(74153sub,
66   logic_input_t m_C[4];
67   logic_input_t m_G;
68
69   logic_output_t m_Y;
70
71   int m_chan;
72);
73
74NETLIB_DEVICE(74153,
75public:
76   NETLIB_NAME(74153sub) m_sub;
77   logic_input_t m_A;
78   logic_input_t m_B;
79);
80
81NETLIB_DEVICE(74153_dip,
82
83   NETLIB_NAME(74153sub) m_1;
84   NETLIB_NAME(74153sub) m_2;
85   logic_input_t m_A;
86   logic_input_t m_B;
87);
88
89NETLIB_NAMESPACE_DEVICES_END()
90
91#endif /* NLD_74153_H_ */
trunk/src/lib/netlist/devices/nld_74175.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_74175.c
5 *
6 */
7
8#include "nld_74175.h"
9
10NETLIB_NAMESPACE_DEVICES_START()
11
12static const netlist_time delay[2] = { NLTIME_FROM_NS(25), NLTIME_FROM_NS(25) };
13static const netlist_time delay_clear[2] = { NLTIME_FROM_NS(40), NLTIME_FROM_NS(25) };
14
15NETLIB_START(74175_sub)
16{
17   register_input("CLK",   m_CLK);
18
19   register_output("Q1",   m_Q[0]);
20   register_output("Q1Q",  m_QQ[0]);
21   register_output("Q2",   m_Q[1]);
22   register_output("Q2Q",  m_QQ[1]);
23   register_output("Q3",   m_Q[2]);
24   register_output("Q3Q",  m_QQ[2]);
25   register_output("Q4",   m_Q[3]);
26   register_output("Q4Q",  m_QQ[3]);
27
28   save(NLNAME(m_clrq));
29   save(NLNAME(m_data));
30}
31
32NETLIB_RESET(74175_sub)
33{
34   m_CLK.set_state(logic_t::STATE_INP_LH);
35   m_clrq = 0;
36   m_data = 0xFF;
37}
38
39NETLIB_UPDATE(74175_sub)
40{
41   if (m_clrq)
42   {
43      for (int i=0; i<4; i++)
44      {
45         UINT8 d = (m_data >> i) & 1;
46         OUTLOGIC(m_Q[i], d, delay[d]);
47         OUTLOGIC(m_QQ[i], d ^ 1, delay[d ^ 1]);
48      }
49      m_CLK.inactivate();
50   }
51}
52
53NETLIB_UPDATE(74175)
54{
55   UINT8 d = 0;
56   for (int i=0; i<4; i++)
57   {
58      d |= (INPLOGIC(m_D[i]) << i);
59   }
60   m_sub.m_clrq = INPLOGIC(m_CLRQ);
61   if (!m_sub.m_clrq)
62   {
63      for (int i=0; i<4; i++)
64      {
65         OUTLOGIC(m_sub.m_Q[i], 0, delay_clear[0]);
66         OUTLOGIC(m_sub.m_QQ[i], 1, delay_clear[1]);
67      }
68      m_sub.m_data = 0;
69   } else if (d != m_sub.m_data)
70   {
71      m_sub.m_data = d;
72      m_sub.m_CLK.activate_lh();
73   }
74}
75
76NETLIB_START(74175)
77{
78   register_sub("sub", m_sub);
79
80   register_subalias("CLK",   m_sub.m_CLK);
81
82   register_input("CLRQ",  m_CLRQ);
83
84   register_input("D1",    m_D[0]);
85   register_subalias("Q1",   m_sub.m_Q[0]);
86   register_subalias("Q1Q",  m_sub.m_QQ[0]);
87
88   register_input("D2",    m_D[1]);
89   register_subalias("Q2",   m_sub.m_Q[1]);
90   register_subalias("Q2Q",  m_sub.m_QQ[1]);
91
92   register_input("D3",    m_D[2]);
93   register_subalias("Q3",   m_sub.m_Q[2]);
94   register_subalias("Q3Q",  m_sub.m_QQ[2]);
95
96   register_input("D4",    m_D[3]);
97   register_subalias("Q4",   m_sub.m_Q[3]);
98   register_subalias("Q4Q",  m_sub.m_QQ[3]);
99
100}
101
102NETLIB_RESET(74175)
103{
104   m_sub.do_reset();
105}
106
107NETLIB_START(74175_dip)
108{
109   register_sub("sub", m_sub);
110
111   register_subalias("9", m_sub.m_CLK);
112   register_input("1",  m_CLRQ);
113
114   register_input("4",    m_D[0]);
115   register_subalias("2",   m_sub.m_Q[0]);
116   register_subalias("3",  m_sub.m_QQ[0]);
117
118   register_input("5",    m_D[1]);
119   register_subalias("7",   m_sub.m_Q[1]);
120   register_subalias("6",  m_sub.m_QQ[1]);
121
122   register_input("12",    m_D[2]);
123   register_subalias("10",   m_sub.m_Q[2]);
124   register_subalias("11",  m_sub.m_QQ[2]);
125
126   register_input("13",    m_D[3]);
127   register_subalias("15",   m_sub.m_Q[3]);
128   register_subalias("14",  m_sub.m_QQ[3]);
129
130}
131
132NETLIB_RESET(74175_dip)
133{
134   NETLIB_NAME(74175)::reset();
135}
136
137NETLIB_UPDATE(74175_dip)
138{
139   NETLIB_NAME(74175)::update();
140}
141
142NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_74175.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_74175.h
5 *
6 *  DM74175: Quad D Flip-Flops with Clear
7 *
8 *          +--------------+
9 *      CLR |1     ++    16| VCC
10 *       Q1 |2           15| Q4
11 *      Q1Q |3           14| Q4Q
12 *       D1 |4   74175   13| D4
13 *       D2 |5           12| D3
14 *      Q2Q |6           11| Q3Q
15 *       Q2 |7           10| Q3
16 *      GND |8            9| CLK
17 *          +--------------+
18 *
19 *          +-----+-----+---++---+-----+
20 *          | CLR | CLK | D || Q | QQ  |
21 *          +=====+=====+===++===+=====+
22 *          |  0  |  X  | X || 0 |  1  |
23 *          |  1  |  R  | 1 || 1 |  0  |
24 *          |  1  |  R  | 0 || 0 |  1  |
25 *          |  1  |  0  | X || Q0| Q0Q |
26 *          +-----+-----+---++---+-----+
27 *
28 *   Q0 The output logic level of Q before the indicated input conditions were established
29 *
30 *  R:  0 --> 1
31 *
32 *  Naming conventions follow National Semiconductor datasheet
33 *
34 */
35
36#ifndef NLD_74175_H_
37#define NLD_74175_H_
38
39#include "nld_signal.h"
40
41#define TTL_74175(_name)                                     \
42      NET_REGISTER_DEV(TTL_74175, _name)
43#define TTL_74175_DIP(_name)                                 \
44      NET_REGISTER_DEV(TTL_74175_DIP, _name)
45
46NETLIB_NAMESPACE_DEVICES_START()
47
48NETLIB_SUBDEVICE(74175_sub,
49
50   logic_input_t m_CLK;
51   logic_output_t m_Q[4];
52   logic_output_t m_QQ[4];
53
54   netlist_sig_t m_clrq;
55   UINT8 m_data;
56);
57
58NETLIB_DEVICE(74175,
59
60   NETLIB_NAME(74175_sub) m_sub;
61   logic_input_t m_D[4];
62   logic_input_t m_CLRQ;
63);
64
65NETLIB_DEVICE_DERIVED_PURE(74175_dip, 74175);
66
67NETLIB_NAMESPACE_DEVICES_END()
68
69#endif /* NLD_74175_H_ */
trunk/src/lib/netlist/devices/nld_74192.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_74192.c
5 *
6 */
7
8#define MAXCNT 9
9
10#include "nld_74192.h"
11
12NETLIB_NAMESPACE_DEVICES_START()
13
14NETLIB_START(74192)
15{
16   register_sub("subABCD", m_ABCD);
17   register_subalias("A", m_ABCD.m_A);
18   register_subalias("B", m_ABCD.m_B);
19   register_subalias("C", m_ABCD.m_C);
20   register_subalias("D", m_ABCD.m_D);
21   register_input("CLEAR",  m_CLEAR);
22   register_input("LOADQ",  m_LOADQ);
23   register_input("CU", m_CU);
24   register_input("CD", m_CD);
25
26   register_output("QA", m_Q[0]);
27   register_output("QB", m_Q[1]);
28   register_output("QC", m_Q[2]);
29   register_output("QD", m_Q[3]);
30   register_output("BORROWQ", m_BORROWQ);
31   register_output("CARRYQ", m_CARRYQ);
32
33   save(NLNAME(m_cnt));
34   save(NLNAME(m_last_CU));
35   save(NLNAME(m_last_CD));
36
37}
38
39NETLIB_RESET(74192)
40{
41   m_cnt = 0;
42   m_last_CU = 0;
43   m_last_CD = 0;
44}
45
46// FIXME: Timing
47/* static */ const netlist_time delay[4] =
48{
49      NLTIME_FROM_NS(40),
50      NLTIME_FROM_NS(40),
51      NLTIME_FROM_NS(40),
52      NLTIME_FROM_NS(40)
53};
54
55NETLIB_UPDATE(74192)
56{
57   int tCarry = 1;
58   int tBorrow = 1;
59   if (INPLOGIC(m_CLEAR))
60   {
61      m_cnt = 0;
62   }
63   else if (!INPLOGIC(m_LOADQ))
64   {
65      m_cnt = m_ABCD.read_ABCD();
66   }
67   else
68   {
69      if (INPLOGIC(m_CD) && !m_last_CU && INPLOGIC(m_CU))
70      {
71         m_cnt++;
72         if (m_cnt > MAXCNT)
73            m_cnt = 0;
74      }
75      if (INPLOGIC(m_CU) && !m_last_CD && INPLOGIC(m_CD))
76      {
77         if (m_cnt > 0)
78            m_cnt--;
79         else
80            m_cnt = MAXCNT;
81      }
82   }
83
84   if (!INPLOGIC(m_CU) && (m_cnt == MAXCNT))
85      tCarry = 0;
86
87   if (!INPLOGIC(m_CD) && (m_cnt == 0))
88      tBorrow = 0;
89
90   m_last_CD = INPLOGIC(m_CD);
91   m_last_CU = INPLOGIC(m_CU);
92
93   for (int i=0; i<4; i++)
94      OUTLOGIC(m_Q[i], (m_cnt >> i) & 1, delay[i]);
95
96   OUTLOGIC(m_BORROWQ, tBorrow, NLTIME_FROM_NS(20)); //FIXME
97   OUTLOGIC(m_CARRYQ, tCarry, NLTIME_FROM_NS(20)); //FIXME
98}
99
100NETLIB_FUNC_VOID(74192, update_outputs, (void))
101{
102}
103
104NETLIB_START(74192_dip)
105{
106   NETLIB_NAME(74192)::start();
107
108   register_subalias("1", m_ABCD.m_B);
109   register_subalias("2", m_Q[1]);
110   register_subalias("3", m_Q[0]);
111   register_subalias("4", m_CD);
112   register_subalias("5", m_CU);
113   register_subalias("6", m_Q[2]);
114   register_subalias("7", m_Q[3]);
115
116   register_subalias("9", m_ABCD.m_D);
117   register_subalias("10", m_ABCD.m_C);
118   register_subalias("11", m_LOADQ);
119   register_subalias("12", m_CARRYQ);
120   register_subalias("13", m_BORROWQ);
121   register_subalias("14", m_CLEAR);
122   register_subalias("15", m_ABCD.m_A);
123
124}
125
126NETLIB_UPDATE(74192_dip)
127{
128   NETLIB_NAME(74192)::update();
129}
130
131NETLIB_RESET(74192_dip)
132{
133   NETLIB_NAME(74192)::reset();
134}
135
136NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_74192.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_74192.h
5 *
6 *  DM74192: Synchronous 4-Bit Binary Counter with Dual Clock
7 *           Decade counter
8 *
9 *  FIXME: This should be merged with the 74193 which counts to 16
10 *
11 *          +--------------+
12 *        B |1     ++    16| VCC
13 *       QB |2           15| A
14 *       QA |3           14| CLEAR
15 *       CD |4    74192  13| BORROWQ
16 *       CU |5           12| CARRYQ
17 *       QC |6           11| LOADQ
18 *       QD |7           10| C
19 *      GND |8            9| D
20 *          +--------------+
21 *
22 * CD: Count up
23 * CU: Count down
24 *
25 *  Naming conventions follow National Semiconductor datasheet
26 *
27 */
28
29#ifndef NLD_74192_H_
30#define NLD_74192_H_
31
32#include "nl_base.h"
33#include "nld_9316.h"
34
35#define TTL_74192(_name)                                              \
36      NET_REGISTER_DEV(TTL_74192, _name)
37
38#define TTL_74192_DIP(_name)                                                         \
39      NET_REGISTER_DEV(TTL_74192_DIP, _name)
40
41NETLIB_NAMESPACE_DEVICES_START()
42
43NETLIB_DEVICE(74192,
44   ATTR_HOT void update_outputs();
45
46   NETLIB_NAME(9316_subABCD) m_ABCD;
47   logic_input_t m_CLEAR;
48   logic_input_t m_LOADQ;
49   logic_input_t m_CU;
50   logic_input_t m_CD;
51
52   INT8 m_cnt;
53   UINT8 m_last_CU;
54   UINT8 m_last_CD;
55
56   logic_output_t m_Q[4];
57   logic_output_t m_BORROWQ;
58   logic_output_t m_CARRYQ;
59);
60
61NETLIB_DEVICE_DERIVED_PURE(74192_dip, 74192);
62
63NETLIB_NAMESPACE_DEVICES_END()
64
65#endif /* NLD_74192_H_ */
trunk/src/lib/netlist/devices/nld_74193.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_74193.c
5 *
6 */
7
8#define MAXCNT 15
9
10#include "nld_74193.h"
11
12NETLIB_NAMESPACE_DEVICES_START()
13
14NETLIB_START(74193)
15{
16   register_input("A", m_A);
17   register_input("B", m_B);
18   register_input("C", m_C);
19   register_input("D", m_D);
20   register_input("CLEAR",  m_CLEAR);
21   register_input("LOADQ",  m_LOADQ);
22   register_input("CU", m_CU);
23   register_input("CD", m_CD);
24
25   register_output("QA", m_Q[0]);
26   register_output("QB", m_Q[1]);
27   register_output("QC", m_Q[2]);
28   register_output("QD", m_Q[3]);
29   register_output("BORROWQ", m_BORROWQ);
30   register_output("CARRYQ", m_CARRYQ);
31
32   save(NLNAME(m_cnt));
33   save(NLNAME(m_last_CU));
34   save(NLNAME(m_last_CD));
35
36}
37
38NETLIB_RESET(74193)
39{
40   m_cnt = 0;
41   m_last_CU = 0;
42   m_last_CD = 0;
43}
44
45// FIXME: Timing
46static const netlist_time delay[4] =
47{
48      NLTIME_FROM_NS(40),
49      NLTIME_FROM_NS(40),
50      NLTIME_FROM_NS(40),
51      NLTIME_FROM_NS(40)
52};
53
54NETLIB_UPDATE(74193)
55{
56   int tCarry = 1;
57   int tBorrow = 1;
58   if (INPLOGIC(m_CLEAR))
59   {
60      m_cnt = 0;
61   }
62   else if (!INPLOGIC(m_LOADQ))
63   {
64      m_cnt = (INPLOGIC(m_D) << 3) | (INPLOGIC(m_C) << 2)
65            | (INPLOGIC(m_B) << 1) | (INPLOGIC(m_A) << 0);
66   }
67   else
68   {
69      if (INPLOGIC(m_CD) && !m_last_CU && INPLOGIC(m_CU))
70      {
71         m_cnt++;
72         if (m_cnt > MAXCNT)
73            m_cnt = 0;
74      }
75      if (INPLOGIC(m_CU) && !m_last_CD && INPLOGIC(m_CD))
76      {
77         if (m_cnt > 0)
78            m_cnt--;
79         else
80            m_cnt = MAXCNT;
81      }
82   }
83
84   if (!INPLOGIC(m_CU) && (m_cnt == MAXCNT))
85      tCarry = 0;
86
87   if (!INPLOGIC(m_CD) && (m_cnt == 0))
88            tBorrow = 0;
89
90   m_last_CD = INPLOGIC(m_CD);
91   m_last_CU = INPLOGIC(m_CU);
92
93   for (int i=0; i<4; i++)
94      OUTLOGIC(m_Q[i], (m_cnt >> i) & 1, delay[i]);
95
96   OUTLOGIC(m_BORROWQ, tBorrow, NLTIME_FROM_NS(20)); //FIXME
97   OUTLOGIC(m_CARRYQ, tCarry, NLTIME_FROM_NS(20)); //FIXME
98}
99
100NETLIB_FUNC_VOID(74193, update_outputs, (void))
101{
102}
103
104NETLIB_START(74193_dip)
105{
106   NETLIB_NAME(74193)::start();
107
108   register_subalias("1", m_B);
109   register_subalias("2", m_Q[1]);
110   register_subalias("3", m_Q[0]);
111   register_subalias("4", m_CD);
112   register_subalias("5", m_CU);
113   register_subalias("6", m_Q[2]);
114   register_subalias("7", m_Q[3]);
115
116   register_subalias("9", m_D);
117   register_subalias("10", m_C);
118   register_subalias("11", m_LOADQ);
119   register_subalias("12", m_CARRYQ);
120   register_subalias("13", m_BORROWQ);
121   register_subalias("14", m_CLEAR);
122   register_subalias("15", m_A);
123
124}
125
126NETLIB_UPDATE(74193_dip)
127{
128   NETLIB_NAME(74193)::update();
129}
130
131NETLIB_RESET(74193_dip)
132{
133   NETLIB_NAME(74193)::reset();
134}
135
136NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_74193.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_74193.h
5 *
6 *  DM74193: Synchronous 4-Bit Binary Counter with Dual Clock
7 *
8 *          +--------------+
9 *        B |1     ++    16| VCC
10 *       QB |2           15| A
11 *       QA |3           14| CLEAR
12 *       CD |4    74193  13| BORROWQ
13 *       CU |5           12| CARRYQ
14 *       QC |6           11| LOADQ
15 *       QD |7           10| C
16 *      GND |8            9| D
17 *          +--------------+
18 *
19 * CD: Count up
20 * CU: Count down
21 *
22 *  Naming conventions follow National Semiconductor datasheet
23 *
24 */
25
26#ifndef NLD_74193_H_
27#define NLD_74193_H_
28
29#include "nl_base.h"
30
31#define TTL_74193(_name)                                              \
32      NET_REGISTER_DEV(TTL_74193, _name)
33
34#define TTL_74193_DIP(_name)                                                         \
35      NET_REGISTER_DEV(TTL_74193_DIP, _name)
36
37NETLIB_NAMESPACE_DEVICES_START()
38
39NETLIB_DEVICE(74193,
40   ATTR_HOT void update_outputs();
41
42   logic_input_t m_A;
43   logic_input_t m_B;
44   logic_input_t m_C;
45   logic_input_t m_D;
46   logic_input_t m_CLEAR;
47   logic_input_t m_LOADQ;
48   logic_input_t m_CU;
49   logic_input_t m_CD;
50
51   INT8 m_cnt;
52   UINT8 m_last_CU;
53   UINT8 m_last_CD;
54
55   logic_output_t m_Q[4];
56   logic_output_t m_BORROWQ;
57   logic_output_t m_CARRYQ;
58);
59
60NETLIB_DEVICE_DERIVED_PURE(74193_dip, 74193);
61
62NETLIB_NAMESPACE_DEVICES_END()
63
64#endif /* NLD_74193_H_ */
trunk/src/lib/netlist/devices/nld_7420.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7420.c
5 *
6 */
7
8#include "nld_7420.h"
9
10NETLIB_NAMESPACE_DEVICES_START()
11
12#if (USE_TRUTHTABLE)
13nld_7420::truthtable_t nld_7420::m_ttbl;
14const char *nld_7420::m_desc[] = {
15      "A,B,C,D|Q",
16      "0,X,X,X|1|22",
17      "X,0,X,X|1|22",
18      "X,X,0,X|1|22",
19      "X,X,X,0|1|22",
20      "1,1,1,1|0|15",
21      ""
22};
23#endif
24
25NETLIB_START(7420_dip)
26{
27   register_sub("1", m_1);
28   register_sub("2", m_2);
29
30   register_subalias("1", m_1.m_I[0]);
31   register_subalias("2", m_1.m_I[1]);
32
33   register_subalias("4", m_1.m_I[2]);
34   register_subalias("5", m_1.m_I[3]);
35   register_subalias("6", m_1.m_Q[0]);
36
37   register_subalias("8", m_2.m_Q[0]);
38   register_subalias("9", m_2.m_I[0]);
39   register_subalias("10", m_2.m_I[1]);
40
41   register_subalias("12", m_2.m_I[2]);
42   register_subalias("13", m_2.m_I[3]);
43
44}
45
46NETLIB_UPDATE(7420_dip)
47{
48   /* only called during startup */
49   m_1.update_dev();
50   m_2.update_dev();
51}
52
53NETLIB_RESET(7420_dip)
54{
55   m_1.do_reset();
56   m_2.do_reset();
57}
58
59NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_7420.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7420.h
5 *
6 *  DM7420: Dual 4-Input NAND Gates
7 *
8 *          +--------------+
9 *       A1 |1     ++    14| VCC
10 *       B1 |2           13| D2
11 *       NC |3           12| C2
12 *       C1 |4    7420   11| NC
13 *       D1 |5           10| B2
14 *       Y1 |6            9| A2
15 *      GND |7            8| Y2
16 *          +--------------+
17 *                  ____
18 *              Y = ABCD
19 *          +---+---+---+---++---+
20 *          | A | B | C | D || Y |
21 *          +===+===+===+===++===+
22 *          | X | X | X | 0 || 1 |
23 *          | X | X | 0 | X || 1 |
24 *          | X | 0 | X | X || 1 |
25 *          | 0 | X | X | X || 1 |
26 *          | 1 | 1 | 1 | 1 || 0 |
27 *          +---+---+---+---++---+
28 *
29 *  Naming conventions follow National Semiconductor datasheet
30 *
31 */
32
33#ifndef NLD_7420_H_
34#define NLD_7420_H_
35
36#include "nld_signal.h"
37#include "nld_truthtable.h"
38
39#define TTL_7420_NAND(_name, _I1, _I2, _I3, _I4)                                    \
40      NET_REGISTER_DEV(TTL_7420_NAND, _name)                                               \
41      NET_CONNECT(_name, A, _I1)                                                  \
42      NET_CONNECT(_name, B, _I2)                                                  \
43      NET_CONNECT(_name, C, _I3)                                                  \
44      NET_CONNECT(_name, D, _I4)
45
46
47#define TTL_7420_DIP(_name)                                                         \
48      NET_REGISTER_DEV(TTL_7420_DIP, _name)
49
50NETLIB_NAMESPACE_DEVICES_START()
51
52#if (USE_TRUTHTABLE)
53NETLIB_TRUTHTABLE(7420, 4, 1, 0);
54#else
55NETLIB_SIGNAL(7420, 4, 0, 0);
56#endif
57
58NETLIB_DEVICE(7420_dip,
59
60   NETLIB_NAME(7420) m_1;
61   NETLIB_NAME(7420) m_2;
62);
63
64NETLIB_NAMESPACE_DEVICES_END()
65
66#endif /* NLD_7420_H_ */
trunk/src/lib/netlist/devices/nld_7425.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7425.c
5 *
6 */
7
8#include "nld_7425.h"
9
10NETLIB_NAMESPACE_DEVICES_START()
11
12NETLIB_START(7425_dip)
13{
14   register_sub("1", m_1);
15   register_sub("2", m_2);
16
17   register_subalias("1", m_1.m_I[0]);
18   register_subalias("2", m_1.m_I[1]);
19
20   //register_subalias("3", ); X1 ==> NC
21
22   register_subalias("4", m_1.m_I[2]);
23   register_subalias("5", m_1.m_I[3]);
24   register_subalias("6", m_1.m_Q[0]);
25
26   register_subalias("8", m_2.m_Q[0]);
27   register_subalias("9", m_2.m_I[0]);
28   register_subalias("10", m_2.m_I[1]);
29
30   //register_subalias("11", ); X2 ==> NC
31
32   register_subalias("12", m_2.m_I[2]);
33   register_subalias("13", m_2.m_I[3]);
34
35}
36
37NETLIB_UPDATE(7425_dip)
38{
39   /* only called during startup */
40   m_1.update_dev();
41   m_2.update_dev();
42}
43
44NETLIB_RESET(7425_dip)
45{
46   m_1.do_reset();
47   m_2.do_reset();
48}
49
50NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_7425.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7425.h
5 *
6 *  DM7425: Dual 4-Input NOR Gates
7 *
8 *          +--------------+
9 *       A1 |1     ++    14| VCC
10 *       B1 |2           13| D2
11 *       X1 |3           12| C2
12 *       C1 |4    7425   11| X2
13 *       D1 |5           10| B2
14 *       Y1 |6            9| A2
15 *      GND |7            8| Y2
16 *          +--------------+
17 *                  _______
18 *              Y = A+B+C+D
19 *          +---+---+---+---+---++---+
20 *          | A | B | C | D | X || Y |
21 *          +===+===+===+===+===++===+
22 *          | X | X | X | X | 0 || Z |
23 *          | 0 | 0 | 0 | 0 | 1 || 1 |
24 *          | X | X | X | 1 | 1 || 0 |
25 *          | X | X | 1 | X | 1 || 0 |
26 *          | X | 1 | X | X | 1 || 0 |
27 *          | 1 | X | X | X | 1 || 0 |
28 *          +---+---+---+---+---++---+
29 *
30 *  TODO: The "X" input and high impedance output are currently not simulated.
31 *
32 *  Naming conventions follow National Semiconductor datasheet
33 *
34 */
35
36#ifndef NLD_7425_H_
37#define NLD_7425_H_
38
39#include "nld_signal.h"
40
41#define TTL_7425_NOR(_name, _I1, _I2, _I3, _I4)                                     \
42      NET_REGISTER_DEV(TTL_7425_NOR, _name)                                               \
43      NET_CONNECT(_name, A, _I1)                                                  \
44      NET_CONNECT(_name, B, _I2)                                                  \
45      NET_CONNECT(_name, C, _I3)                                                  \
46      NET_CONNECT(_name, D, _I4)
47
48#define TTL_7425_DIP(_name)                                                         \
49      NET_REGISTER_DEV(TTL_7425_DIP, _name)
50
51NETLIB_NAMESPACE_DEVICES_START()
52
53NETLIB_SIGNAL(7425, 4, 1, 0);
54
55NETLIB_DEVICE(7425_dip,
56
57   NETLIB_NAME(7425) m_1;
58   NETLIB_NAME(7425) m_2;
59);
60
61NETLIB_NAMESPACE_DEVICES_END()
62
63#endif /* NLD_7425_H_ */
trunk/src/lib/netlist/devices/nld_7427.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7427.c
5 *
6 */
7
8#include "nld_7427.h"
9
10#include "nld_7402.h"
11
12NETLIB_NAMESPACE_DEVICES_START()
13
14#if (USE_TRUTHTABLE)
15nld_7427::truthtable_t nld_7427::m_ttbl;
16const char *nld_7427::m_desc[] = {
17      "A,B,C|Q ",
18      "0,0,0|1|22",
19      "1,X,X|0|15",
20      "X,1,X|0|15",
21      "X,X,1|0|15",
22      ""
23};
24#endif
25
26NETLIB_START(7427_dip)
27{
28   register_sub("1", m_1);
29   register_sub("2", m_2);
30   register_sub("3", m_3);
31
32   register_subalias("1", m_1.m_I[0]);
33   register_subalias("2", m_1.m_I[1]);
34   register_subalias("3", m_2.m_I[0]);
35   register_subalias("4", m_2.m_I[1]);
36   register_subalias("5", m_2.m_I[2]);
37   register_subalias("6", m_2.m_Q[0]);
38
39   register_subalias("8", m_3.m_Q[0]);
40   register_subalias("9", m_3.m_I[0]);
41   register_subalias("10", m_3.m_I[1]);
42   register_subalias("11", m_3.m_I[2]);
43
44   register_subalias("12", m_1.m_Q[0]);
45   register_subalias("13", m_1.m_I[2]);
46}
47
48NETLIB_UPDATE(7427_dip)
49{
50   /* only called during startup */
51   m_1.update_dev();
52   m_2.update_dev();
53   m_3.update_dev();
54}
55
56NETLIB_RESET(7427_dip)
57{
58   m_1.do_reset();
59   m_2.do_reset();
60   m_3.do_reset();
61}
62
63NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_7427.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7427.h
5 *
6 *  DM7427: Triple 3-Input NOR Gates
7 *
8 *          +--------------+
9 *       A1 |1     ++    14| VCC
10 *       B1 |2           13| C1
11 *       A2 |3           12| Y1
12 *       B2 |4    7427   11| C3
13 *       C2 |5           10| B3
14 *       Y2 |6            9| A3
15 *      GND |7            8| Y3
16 *          +--------------+
17 *                  _____
18 *              Y = A+B+C
19 *          +---+---+---++---+
20 *          | A | B | C || Y |
21 *          +===+===+===++===+
22 *          | X | X | 1 || 0 |
23 *          | X | 1 | X || 0 |
24 *          | 1 | X | X || 0 |
25 *          | 0 | 0 | 0 || 1 |
26 *          +---+---+---++---+
27 *
28 *  Naming conventions follow National Semiconductor datasheet
29 *
30 */
31
32#ifndef NLD_7427_H_
33#define NLD_7427_H_
34
35#include "nld_signal.h"
36#include "nld_truthtable.h"
37
38#define TTL_7427_NOR(_name, _I1, _I2, _I3)                                          \
39      NET_REGISTER_DEV(TTL_7427_NOR, _name)                                               \
40      NET_CONNECT(_name, A, _I1)                                                  \
41      NET_CONNECT(_name, B, _I2)                                                  \
42      NET_CONNECT(_name, C, _I3)
43
44#define TTL_7427_DIP(_name)                                                         \
45      NET_REGISTER_DEV(TTL_7427_DIP, _name)
46
47NETLIB_NAMESPACE_DEVICES_START()
48
49#if (USE_TRUTHTABLE)
50NETLIB_TRUTHTABLE(7427, 3, 1, 0);
51#else
52NETLIB_SIGNAL(7427, 3, 1, 0);
53#endif
54
55NETLIB_DEVICE(7427_dip,
56
57   NETLIB_NAME(7427) m_1;
58   NETLIB_NAME(7427) m_2;
59   NETLIB_NAME(7427) m_3;
60);
61
62NETLIB_NAMESPACE_DEVICES_END()
63
64
65#endif /* NLD_7427_H_ */
trunk/src/lib/netlist/devices/nld_74279.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_74279.c
5 *
6 */
7
8#include "nld_74279.h"
9
10NETLIB_NAMESPACE_DEVICES_START()
11
12nld_74279A::truthtable_t nld_74279A::m_ttbl;
13nld_74279B::truthtable_t nld_74279B::m_ttbl;
14
15#if 0
16const char *nld_74279A::m_desc[] = {
17      "S,R,PQ,PS,PR|Q",
18      "0,0,X,X,X|1|22",
19      "0,1,X,X,X|1|22",
20      "1,0,X,X,X|0|15",
21      "1,1,0,X,X|0|15",
22      "1,1,1,X,X|1|22",
23      ""
24};
25
26
27const char *nld_74279B::m_desc[] = {
28      "S1,S2,R,PQ,PS1,PS2,PR|Q",
29      "0,X,0,X,X,X,X|1|22",
30      "X,0,0,X,X,X,X|1|22",
31      "0,X,1,X,X,X,X|1|22",
32      "X,0,1,X,X,X,X|1|22",
33      "1,1,0,X,X,X,X|0|15",
34      "1,1,1,0,X,X,X|0|15",
35      "1,1,1,1,X,X,X|1|22",
36      ""
37};
38#else
39#if 1
40const char *nld_74279A::m_desc[] = {
41      "S,R,_Q|Q",
42      "0,X,X|1|22",
43      "1,0,X|0|27",
44      "1,1,0|0|27", //15
45      "1,1,1|1|22",
46      ""
47};
48
49
50const char *nld_74279B::m_desc[] = {
51      "S1,S2,R,_Q|Q",
52      "0,X,X,X|1|22",
53      "X,0,X,X|1|22",
54      "1,1,0,X|0|27",
55      "1,1,1,0|0|27", // 15
56      "1,1,1,1|1|22",
57      ""
58};
59#else
60const char *nld_74279A::m_desc[] = {
61      " S, R,_Q,_QR|Q,QR",
62      " 0, 0, 0, 0 |1, 1|20,22",
63      " 1, 0, 0, 0 |1, 1|20,22",
64      " 0, 1, 0, 0 |1, 1|20,22",
65      " 1, 1, 0, 0 |1, 1|20,22",
66      " 0, 0, 1, 0 |1, 1|20,22",
67      " 1, 0, 1, 0 |1, 1|20,22",
68      " 0, 1, 1, 0 |1, 0|22,15",
69      " 1, 1, 1, 0 |1, 0|22,15",
70      " 0, 0, 0, 1 |1, 1|20,22",
71      " 1, 0, 0, 1 |0, 1|15,22",
72      " 0, 1, 0, 1 |1, 1|20,22",
73      " 1, 1, 0, 1 |0, 1|15,22",
74      " 0, 0, 1, 1 |1, 1|20,22",
75      " 1, 0, 1, 1 |0, 1|15,22",
76      " 0, 1, 1, 1 |1, 0|22,15",
77      " 1, 1, 1, 1 |0, 0|13,15",
78      ""
79};
80
81
82const char *nld_74279B::m_desc[] = {
83      "S1,S2,R,_Q,_QR|Q,QR",
84      "0,0,0,0,0|1,1|20,22",
85      "1,0,0,0,0|1,1|20,22",
86      "0,1,0,0,0|1,1|20,22",
87      "1,1,0,0,0|1,1|20,22",
88      "0,0,1,0,0|1,1|20,22",
89      "1,0,1,0,0|1,1|20,22",
90      "0,1,1,0,0|1,1|20,22",
91      "1,1,1,0,0|1,1|20,22",
92      "0,0,0,1,0|1,1|20,22",
93      "1,0,0,1,0|1,1|20,22",
94      "0,1,0,1,0|1,1|20,22",
95      "1,1,0,1,0|1,1|20,22",
96      "0,0,1,1,0|1,0|22,15",
97      "1,0,1,1,0|1,0|22,15",
98      "0,1,1,1,0|1,0|22,15",
99      "1,1,1,1,0|1,0|22,15",
100      "0,0,0,0,1|1,1|20,22",
101      "1,0,0,0,1|1,1|20,22",
102      "0,1,0,0,1|1,1|20,22",
103      "1,1,0,0,1|0,1|15,22",
104      "0,0,1,0,1|1,1|20,22",
105      "1,0,1,0,1|1,1|20,22",
106      "0,1,1,0,1|1,1|20,22",
107      "1,1,1,0,1|0,1|15,22",
108      "0,0,0,1,1|1,1|20,22",
109      "1,0,0,1,1|1,1|20,22",
110      "0,1,0,1,1|1,1|20,22",
111      "1,1,0,1,1|0,1|15,22",
112      "0,0,1,1,1|1,0|22,15",
113      "1,0,1,1,1|1,0|22,15",
114      "0,1,1,1,1|1,0|22,15",
115      "1,1,1,1,1|0,0|13,15",
116      ""
117};
118
119#endif
120#endif
121
122
123NETLIB_START(74279_dip)
124{
125   register_sub("1", m_1);
126   register_sub("2", m_2);
127   register_sub("3", m_3);
128   register_sub("4", m_4);
129
130   register_subalias("1", m_1.m_I[2]);  //R
131   register_subalias("2", m_1.m_I[0]);
132   register_subalias("3", m_1.m_I[1]);
133   register_subalias("4", m_1.m_Q[0]);
134
135   register_subalias("5", m_2.m_I[1]);  //R
136   register_subalias("6", m_2.m_I[0]);
137   register_subalias("7", m_2.m_Q[0]);
138
139   register_subalias("9", m_3.m_Q[0]);
140   register_subalias("10", m_3.m_I[2]); //R
141   register_subalias("11", m_3.m_I[0]);
142   register_subalias("12", m_3.m_I[1]);
143
144   register_subalias("13", m_4.m_Q[0]);
145   register_subalias("14", m_4.m_I[1]); //R
146   register_subalias("15", m_4.m_I[0]);
147}
148
149NETLIB_UPDATE(74279_dip)
150{
151   /* only called during startup */
152   m_1.update_dev();
153   m_2.update_dev();
154   m_3.update_dev();
155   m_4.update_dev();
156}
157
158NETLIB_RESET(74279_dip)
159{
160   m_1.do_reset();
161   m_2.do_reset();
162   m_3.do_reset();
163   m_4.do_reset();
164}
165
166NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_74279.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_74279.h
5 *
6 *  DM74279: Quad S-R Latch
7 *
8 *          +--------------+
9 *       1R |1     ++    16| VCC
10 *      1S1 |2           15| 4S
11 *      1S2 |3           14| 4R
12 *       1Q |4    74279  13| 4Q
13 *       2R |5           12| 3S2
14 *       2S |6           11| 3S1
15 *       2Q |7           10| 3R
16 *      GND |8            9| 3Q
17 *          +--------------+
18 *                  ___
19 *
20 *          +---+---+---++---+
21 *          |S1 |S2 | R || Q |
22 *          +===+===+===++===+
23 *          | 0 | 0 | 0 || 1 |
24 *          | 0 | 1 | 1 || 1 |
25 *          | 1 | 0 | 1 || 1 |
26 *          | 1 | 1 | 0 || 0 |
27 *          | 1 | 1 | 1 ||QP |
28 *          +---+---+---++---+
29 *
30 *  QP: Previous Q
31 *
32 *  Naming conventions follow Fairchild Semiconductor datasheet
33 *
34 */
35
36#ifndef NLD_74279_H_
37#define NLD_74279_H_
38
39#include "nld_truthtable.h"
40
41#define TTL_74279_DIP(_name)                                                         \
42      NET_REGISTER_DEV(TTL_74279_DIP, _name)
43
44NETLIB_NAMESPACE_DEVICES_START()
45
46#if 0
47NETLIB_TRUTHTABLE(74279A, 2, 1, 1);
48NETLIB_TRUTHTABLE(74279B, 3, 1, 1);
49#else
50NETLIB_TRUTHTABLE(74279A, 3, 1, 0);
51NETLIB_TRUTHTABLE(74279B, 4, 1, 0);
52//NETLIB_TRUTHTABLE(74279A, 4, 2, 0);
53//NETLIB_TRUTHTABLE(74279B, 5, 2, 0);
54#endif
55
56NETLIB_DEVICE(74279_dip,
57
58   NETLIB_NAME(74279B) m_1;
59   NETLIB_NAME(74279A) m_2;
60   NETLIB_NAME(74279B) m_3;
61   NETLIB_NAME(74279A) m_4;
62);
63
64NETLIB_NAMESPACE_DEVICES_END()
65
66#endif /* NLD_74279_H_ */
trunk/src/lib/netlist/devices/nld_7430.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7430.c
5 *
6 */
7
8#include "nld_7430.h"
9
10NETLIB_NAMESPACE_DEVICES_START()
11
12#if (USE_TRUTHTABLE)
13nld_7430::truthtable_t nld_7430::m_ttbl;
14const char *nld_7430::m_desc[] = {
15      "A,B,C,D,E,F,G,H|Q ",
16      "0,X,X,X,X,X,X,X|1|22",
17      "X,0,X,X,X,X,X,X|1|22",
18      "X,X,0,X,X,X,X,X|1|22",
19      "X,X,X,0,X,X,X,X|1|22",
20      "X,X,X,X,0,X,X,X|1|22",
21      "X,X,X,X,X,0,X,X|1|22",
22      "X,X,X,X,X,X,0,X|1|22",
23      "X,X,X,X,X,X,X,0|1|22",
24      "1,1,1,1,1,1,1,1|0|15",
25      ""
26};
27
28#endif
29
30
31NETLIB_START(7430_dip)
32{
33   register_sub("1", m_1);
34
35   register_subalias("1", m_1.m_I[0]);
36   register_subalias("2", m_1.m_I[1]);
37   register_subalias("3", m_1.m_I[2]);
38   register_subalias("4", m_1.m_I[3]);
39   register_subalias("5", m_1.m_I[4]);
40   register_subalias("6", m_1.m_I[5]);
41
42   register_subalias("8", m_1.m_Q[0]);
43
44   register_subalias("11", m_1.m_I[6]);
45   register_subalias("12", m_1.m_I[7]);
46}
47
48NETLIB_UPDATE(7430_dip)
49{
50   /* only called during startup */
51   m_1.update_dev();
52}
53
54NETLIB_RESET(7430_dip)
55{
56   m_1.do_reset();
57}
58
59NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_7430.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7430.h
5 *
6 *  DM7430: 8-Input NAND Gate
7 *
8 *          +--------------+
9 *       A  |1     ++    14| VCC
10 *       B  |2           13| NC
11 *       C  |3           12| H
12 *       D  |4    7430   11| G
13 *       E  |5           10| NC
14 *       F  |6            9| NC
15 *      GND |7            8| Y
16 *          +--------------+
17 *                  ________
18 *              Y = ABCDEFGH
19 *          +---+---+---+---+---+---+---+---++---+
20 *          | A | B | C | D | E | F | G | H || Y |
21 *          +===+===+===+===+===+===+===+===++===+
22 *          | X | X | X | X | X | X | X | 0 || 1 |
23 *          | X | X | X | X | X | X | 0 | X || 1 |
24 *          | X | X | X | X | X | 0 | X | X || 1 |
25 *          | X | X | X | X | 0 | X | X | X || 1 |
26 *          | X | X | X | 0 | X | X | X | X || 1 |
27 *          | X | X | 0 | X | X | X | X | X || 1 |
28 *          | X | 0 | X | X | X | X | X | X || 1 |
29 *          | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 || 0 |
30 *          +---+---+---+---+---+---+---+---++---+
31 *
32 *  Naming conventions follow National Semiconductor datasheet
33 *
34 */
35
36
37#ifndef NLD_7430_H_
38#define NLD_7430_H_
39
40#include "nld_signal.h"
41#include "nld_truthtable.h"
42
43#define TTL_7430_NAND(_name, _I1, _I2, _I3, _I4, _I5, _I6, _I7, _I8)                \
44      NET_REGISTER_DEV(TTL_7430_NAND, _name)                                               \
45      NET_CONNECT(_name, A, _I1)                                                  \
46      NET_CONNECT(_name, B, _I2)                                                  \
47      NET_CONNECT(_name, C, _I3)                                                  \
48      NET_CONNECT(_name, D, _I4)                                                  \
49      NET_CONNECT(_name, E, _I5)                                                  \
50      NET_CONNECT(_name, F, _I6)                                                  \
51      NET_CONNECT(_name, G, _I7)                                                  \
52      NET_CONNECT(_name, H, _I8)
53
54
55#define TTL_7430_DIP(_name)                                                         \
56      NET_REGISTER_DEV(TTL_7430_DIP, _name)
57
58NETLIB_NAMESPACE_DEVICES_START()
59
60#if (USE_TRUTHTABLE)
61NETLIB_TRUTHTABLE(7430, 8, 1, 0);
62#else
63NETLIB_SIGNAL(7430, 8, 0, 0);
64#endif
65
66
67NETLIB_DEVICE(7430_dip,
68
69   NETLIB_NAME(7430) m_1;
70);
71
72NETLIB_NAMESPACE_DEVICES_END()
73
74
75#endif /* NLD_7430_H_ */
trunk/src/lib/netlist/devices/nld_7432.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7432.c
5 *
6 */
7
8#include "nld_7432.h"
9
10NETLIB_NAMESPACE_DEVICES_START()
11
12#if (USE_TRUTHTABLE)
13nld_7432::truthtable_t nld_7432::m_ttbl;
14const char *nld_7432::m_desc[] = {
15      "A,B|Q ",
16      "1,X|1|22",
17      "0,1|1|22",
18      "0,0|0|15",
19      ""
20};
21
22#endif
23
24NETLIB_START(7432_dip)
25{
26   register_sub("1", m_1);
27   register_sub("2", m_2);
28   register_sub("3", m_3);
29   register_sub("4", m_4);
30
31   register_subalias("3", m_1.m_Q[0]);
32   register_subalias("1", m_1.m_I[0]);
33   register_subalias("2", m_1.m_I[1]);
34
35   register_subalias("6", m_2.m_Q[0]);
36   register_subalias("4", m_2.m_I[0]);
37   register_subalias("5", m_2.m_I[1]);
38
39   register_subalias("9", m_3.m_I[0]);
40   register_subalias("10", m_3.m_I[1]);
41   register_subalias("8", m_3.m_Q[0]);
42
43   register_subalias("12", m_4.m_I[0]);
44   register_subalias("13", m_4.m_I[1]);
45   register_subalias("11", m_4.m_Q[0]);
46}
47
48NETLIB_UPDATE(7432_dip)
49{
50   /* only called during startup */
51   m_1.update_dev();
52   m_2.update_dev();
53   m_3.update_dev();
54   m_4.update_dev();
55}
56
57NETLIB_RESET(7432_dip)
58{
59   m_1.do_reset();
60   m_2.do_reset();
61   m_3.do_reset();
62   m_4.do_reset();
63}
64
65NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_7432.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7432.h
5 *
6 *  DM7432: Quad 2-Input OR Gates
7 *
8 *          +--------------+
9 *       A1 |1     ++    14| VCC
10 *       B1 |2           13| B4
11 *       Y1 |3           12| A4
12 *       A2 |4    7432   11| Y4
13 *       B2 |5           10| B3
14 *       Y2 |6            9| A3
15 *      GND |7            8| Y3
16 *          +--------------+
17 *                  ___
18 *              Y = A+B
19 *          +---+---++---+
20 *          | A | B || Y |
21 *          +===+===++===+
22 *          | 0 | 0 || 0 |
23 *          | 0 | 1 || 1 |
24 *          | 1 | 0 || 1 |
25 *          | 1 | 1 || 1 |
26 *          +---+---++---+
27 *
28 *  Naming conventions follow National Semiconductor datasheet
29 *
30 */
31
32#ifndef NLD_7432_H_
33#define NLD_7432_H_
34
35#include "nld_signal.h"
36#include "nld_truthtable.h"
37
38#define TTL_7432_OR(_name, _I1, _I2)                                           \
39      NET_REGISTER_DEV(TTL_7432_OR, _name)                                   \
40      NET_CONNECT(_name, A, _I1)                                             \
41      NET_CONNECT(_name, B, _I2)
42
43#define TTL_7432_DIP(_name)                                                    \
44      NET_REGISTER_DEV(TTL_7432_DIP, _name)
45
46NETLIB_NAMESPACE_DEVICES_START()
47
48#if (USE_TRUTHTABLE)
49NETLIB_TRUTHTABLE(7432, 2, 1, 0);
50#else
51NETLIB_SIGNAL(7432, 2, 1, 1);
52#endif
53
54NETLIB_DEVICE(7432_dip,
55
56   NETLIB_NAME(7432) m_1;
57   NETLIB_NAME(7432) m_2;
58   NETLIB_NAME(7432) m_3;
59   NETLIB_NAME(7432) m_4;
60);
61
62NETLIB_NAMESPACE_DEVICES_END()
63
64#endif /* NLD_7432_H_ */
trunk/src/lib/netlist/devices/nld_7437.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7437.c
5 *
6 */
7
8#include "nld_7437.h"
9
10NETLIB_NAMESPACE_DEVICES_START()
11
12#if (USE_TRUTHTABLE)
13nld_7437::truthtable_t nld_7437::m_ttbl;
14const char *nld_7437::m_desc[] = {
15      "A , B | Q ",
16      "0,X|1|22",
17      "X,0|1|22",
18      "1,1|0|15",
19      ""
20};
21
22#endif
23
24NETLIB_START(7437_dip)
25{
26   register_sub("1", m_1);
27   register_sub("2", m_2);
28   register_sub("3", m_3);
29   register_sub("4", m_4);
30
31   register_subalias("1", m_1.m_I[0]);
32   register_subalias("2", m_1.m_I[1]);
33   register_subalias("3", m_1.m_Q[0]);
34
35   register_subalias("4", m_2.m_I[0]);
36   register_subalias("5", m_2.m_I[1]);
37   register_subalias("6", m_2.m_Q[0]);
38
39   register_subalias("9", m_3.m_I[0]);
40   register_subalias("10", m_3.m_I[1]);
41   register_subalias("8", m_3.m_Q[0]);
42
43   register_subalias("12", m_4.m_I[0]);
44   register_subalias("13", m_4.m_I[1]);
45   register_subalias("11", m_4.m_Q[0]);
46}
47
48NETLIB_UPDATE(7437_dip)
49{
50   /* only called during startup */
51   m_1.update_dev();
52   m_2.update_dev();
53   m_3.update_dev();
54   m_4.update_dev();
55}
56
57NETLIB_RESET(7437_dip)
58{
59   m_1.do_reset();
60   m_2.do_reset();
61   m_3.do_reset();
62   m_4.do_reset();
63}
64
65NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_7437.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7437.h
5 *
6 *  DM7437: Quad 2-Input NAND Gates
7 *
8 *          +--------------+
9 *       A1 |1     ++    14| VCC
10 *       B1 |2           13| B4
11 *       Y1 |3           12| A4
12 *       A2 |4    7437   11| Y4
13 *       B2 |5           10| B3
14 *       Y2 |6            9| A3
15 *      GND |7            8| Y3
16 *          +--------------+
17 *                  __
18 *              Y = AB
19 *          +---+---++---+
20 *          | A | B || Y |
21 *          +===+===++===+
22 *          | 0 | 0 || 1 |
23 *          | 0 | 1 || 1 |
24 *          | 1 | 0 || 1 |
25 *          | 1 | 1 || 0 |
26 *          +---+---++---+
27 *
28 *  Naming conventions follow National Semiconductor datasheet
29 *
30 *  FIXME: Same as 7400, but drains higher output currents.
31 *         Netlist currently does not model over currents (should it ever?)
32 *
33 */
34
35#ifndef NLD_7437_H_
36#define NLD_7437_H_
37
38#include "nld_signal.h"
39#include "nld_truthtable.h"
40
41#define TTL_7437_NAND(_name, _A, _B)                                                \
42      NET_REGISTER_DEV(TTL_7437_NAND, _name)                                               \
43      NET_CONNECT(_name, A, _A)                                                   \
44      NET_CONNECT(_name, B, _B)
45
46#define TTL_7437_DIP(_name)                                                         \
47      NET_REGISTER_DEV(TTL_7437_DIP, _name)
48
49NETLIB_NAMESPACE_DEVICES_START()
50
51#if (USE_TRUTHTABLE)
52NETLIB_TRUTHTABLE(7437, 2, 1, 0);
53#else
54NETLIB_SIGNAL(7437, 2, 0, 0);
55#endif
56
57NETLIB_DEVICE(7437_dip,
58
59   NETLIB_NAME(7437) m_1;
60   NETLIB_NAME(7437) m_2;
61   NETLIB_NAME(7437) m_3;
62   NETLIB_NAME(7437) m_4;
63);
64
65NETLIB_NAMESPACE_DEVICES_END()
66
67#endif /* NLD_7437_H_ */
trunk/src/lib/netlist/devices/nld_7448.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7448.c
5 *
6 */
7
8#include "nld_7448.h"
9
10NETLIB_NAMESPACE_DEVICES_START()
11
12#if (0 && USE_TRUTHTABLE)
13nld_7448::truthtable_t nld_7448::m_ttbl;
14const char *nld_7448::m_desc[] = {
15      " LTQ,BIQ,RBIQ, A , B , C , D | a, b, c, d, e, f, g",
16
17      "  1,  1,  1,   0,  0,  0,  0 | 1, 1, 1, 1, 1, 1, 0|100,100,100,100,100,100,100",
18      "  1,  1,  X,   1,  0,  0,  0 | 0, 1, 1, 0, 0, 0, 0|100,100,100,100,100,100,100",
19      "  1,  1,  X,   0,  1,  0,  0 | 1, 1, 0, 1, 1, 0, 1|100,100,100,100,100,100,100",
20      "  1,  1,  X,   1,  1,  0,  0 | 1, 1, 1, 1, 0, 0, 1|100,100,100,100,100,100,100",
21      "  1,  1,  X,   0,  0,  1,  0 | 0, 1, 1, 0, 0, 1, 1|100,100,100,100,100,100,100",
22      "  1,  1,  X,   1,  0,  1,  0 | 1, 0, 1, 1, 0, 1, 1|100,100,100,100,100,100,100",
23      "  1,  1,  X,   0,  1,  1,  0 | 0, 0, 1, 1, 1, 1, 1|100,100,100,100,100,100,100",
24      "  1,  1,  X,   1,  1,  1,  0 | 1, 1, 1, 0, 0, 0, 0|100,100,100,100,100,100,100",
25      "  1,  1,  X,   0,  0,  0,  1 | 1, 1, 1, 1, 1, 1, 1|100,100,100,100,100,100,100",
26      "  1,  1,  X,   1,  0,  0,  1 | 1, 1, 1, 0, 0, 1, 1|100,100,100,100,100,100,100",
27      "  1,  1,  X,   0,  1,  0,  1 | 0, 0, 0, 1, 1, 0, 1|100,100,100,100,100,100,100",
28      "  1,  1,  X,   1,  1,  0,  1 | 0, 0, 1, 1, 0, 0, 1|100,100,100,100,100,100,100",
29      "  1,  1,  X,   0,  0,  1,  1 | 0, 1, 0, 0, 0, 1, 1|100,100,100,100,100,100,100",
30      "  1,  1,  X,   1,  0,  1,  1 | 1, 0, 0, 1, 0, 1, 1|100,100,100,100,100,100,100",
31      "  1,  1,  X,   0,  1,  1,  1 | 0, 0, 0, 1, 1, 1, 1|100,100,100,100,100,100,100",
32      "  1,  1,  X,   1,  1,  1,  1 | 0, 0, 0, 0, 0, 0, 0|100,100,100,100,100,100,100",
33
34      // BI/RBO is input output. In the next case it is used as an output will go low.
35      "  1,  1,  0,   0,  0,  0,  0 | 0, 0, 0, 0, 0, 0, 0|100,100,100,100,100,100,100", // RBI
36
37      "  0,  1,  X,   X,  X,  X,  X | 1, 1, 1, 1, 1, 1, 1|100,100,100,100,100,100,100", // LT
38
39      // This condition has precedence
40      "  X,  0,  X,   X,  X,  X,  X | 0, 0, 0, 0, 0, 0, 0|100,100,100,100,100,100,100", // BI
41      ""
42};
43
44NETLIB_START(7448_dip)
45{
46   NETLIB_NAME(7448)::start();
47
48   register_subalias("1", m_i[4]); // B
49   register_subalias("2", m_i[5]); // C
50   register_subalias("3", m_i[0]); // LTQ
51   register_subalias("4", m_i[1]); // BIQ
52   register_subalias("5", m_i[2]); // RBIQ
53   register_subalias("6", m_i[6]); // D
54   register_subalias("7", m_i[3]); // A
55
56   register_subalias("9",  m_Q[4]); // e
57   register_subalias("10", m_Q[3]); // d
58   register_subalias("11", m_Q[2]); // c
59   register_subalias("12", m_Q[1]); // b
60   register_subalias("13", m_Q[0]); // a
61   register_subalias("14", m_Q[6]); // g
62   register_subalias("15", m_Q[5]); // f
63}
64
65#else
66NETLIB_START(7448)
67{
68   register_sub("sub", sub);
69
70   register_subalias("A", sub.m_A);
71   register_subalias("B", sub.m_B);
72   register_subalias("C", sub.m_C);
73   register_subalias("D", sub.m_D);
74   register_input("LTQ", m_LTQ);
75   register_input("BIQ", m_BIQ);
76   register_subalias("RBIQ",sub.m_RBIQ);
77
78   register_subalias("a", sub.m_Q[0]);
79   register_subalias("b", sub.m_Q[1]);
80   register_subalias("c", sub.m_Q[2]);
81   register_subalias("d", sub.m_Q[3]);
82   register_subalias("e", sub.m_Q[4]);
83   register_subalias("f", sub.m_Q[5]);
84   register_subalias("g", sub.m_Q[6]);
85
86}
87
88
89NETLIB_RESET(7448)
90{
91   sub.do_reset();
92}
93
94NETLIB_UPDATE(7448)
95{
96   if (INPLOGIC(m_BIQ) && !INPLOGIC(m_LTQ))
97   {
98      sub.update_outputs(8);
99   }
100   else if (!INPLOGIC(m_BIQ))
101   {
102      sub.update_outputs(15);
103   }
104
105   if (!INPLOGIC(m_BIQ) || (INPLOGIC(m_BIQ) && !INPLOGIC(m_LTQ)))
106   {
107      sub.m_A.inactivate();
108      sub.m_B.inactivate();
109      sub.m_C.inactivate();
110      sub.m_D.inactivate();
111      sub.m_RBIQ.inactivate();
112   } else {
113      sub.m_RBIQ.activate();
114      sub.m_D.activate();
115      sub.m_C.activate();
116      sub.m_B.activate();
117      sub.m_A.activate();
118      sub.update();
119   }
120
121}
122
123NETLIB_START(7448_sub)
124{
125   register_input("A0", m_A);
126   register_input("A1", m_B);
127   register_input("A2", m_C);
128   register_input("A3", m_D);
129   register_input("RBIQ", m_RBIQ);
130
131   register_output("a", m_Q[0]);
132   register_output("b", m_Q[1]);
133   register_output("c", m_Q[2]);
134   register_output("d", m_Q[3]);
135   register_output("e", m_Q[4]);
136   register_output("f", m_Q[5]);
137   register_output("g", m_Q[6]);
138
139   save(NLNAME(m_state));
140}
141
142NETLIB_RESET(7448_sub)
143{
144   m_state = 0;
145}
146
147NETLIB_UPDATE(7448_sub)
148{
149   UINT8 v;
150
151   v = (INPLOGIC(m_A) << 0) | (INPLOGIC(m_B) << 1) | (INPLOGIC(m_C) << 2) | (INPLOGIC(m_D) << 3);
152   if ((!INPLOGIC(m_RBIQ) && (v==0)))
153         v = 15;
154   update_outputs(v);
155}
156
157NETLIB_FUNC_VOID(7448_sub, update_outputs, (UINT8 v))
158{
159   nl_assert(v<16);
160   if (v != m_state)
161   {
162      // max transfer time is 100 NS */
163
164      for (int i=0; i<7; i++)
165         OUTLOGIC(m_Q[i], tab7448[v][i], NLTIME_FROM_NS(100));
166      m_state = v;
167   }
168}
169
170const UINT8 NETLIB_NAME(7448_sub)::tab7448[16][7] =
171{
172      {   1, 1, 1, 1, 1, 1, 0 },  /* 00 - not blanked ! */
173      {   0, 1, 1, 0, 0, 0, 0 },  /* 01 */
174      {   1, 1, 0, 1, 1, 0, 1 },  /* 02 */
175      {   1, 1, 1, 1, 0, 0, 1 },  /* 03 */
176      {   0, 1, 1, 0, 0, 1, 1 },  /* 04 */
177      {   1, 0, 1, 1, 0, 1, 1 },  /* 05 */
178      {   0, 0, 1, 1, 1, 1, 1 },  /* 06 */
179      {   1, 1, 1, 0, 0, 0, 0 },  /* 07 */
180      {   1, 1, 1, 1, 1, 1, 1 },  /* 08 */
181      {   1, 1, 1, 0, 0, 1, 1 },  /* 09 */
182      {   0, 0, 0, 1, 1, 0, 1 },  /* 10 */
183      {   0, 0, 1, 1, 0, 0, 1 },  /* 11 */
184      {   0, 1, 0, 0, 0, 1, 1 },  /* 12 */
185      {   1, 0, 0, 1, 0, 1, 1 },  /* 13 */
186      {   0, 0, 0, 1, 1, 1, 1 },  /* 14 */
187      {   0, 0, 0, 0, 0, 0, 0 },  /* 15 */
188};
189
190NETLIB_START(7448_dip)
191{
192   NETLIB_NAME(7448)::start();
193
194   register_subalias("1", sub.m_B);
195   register_subalias("2", sub.m_C);
196   register_subalias("3", m_LTQ);
197   register_subalias("4", m_BIQ);
198   register_subalias("5",sub.m_RBIQ);
199   register_subalias("6", sub.m_D);
200   register_subalias("7", sub.m_A);
201
202   register_subalias("9",  sub.m_Q[4]); // e
203   register_subalias("10", sub.m_Q[3]); // d
204   register_subalias("11", sub.m_Q[2]); // c
205   register_subalias("12", sub.m_Q[1]); // b
206   register_subalias("13", sub.m_Q[0]); // a
207   register_subalias("14", sub.m_Q[6]); // g
208   register_subalias("15", sub.m_Q[5]); // f
209}
210
211#endif
212
213NETLIB_UPDATE(7448_dip)
214{
215   NETLIB_NAME(7448)::update();
216}
217
218NETLIB_RESET(7448_dip)
219{
220   NETLIB_NAME(7448)::reset();
221}
222
223NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_7448.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7448.h
5 *
6 *  DM7448: BCD to 7-Segment decoders/drivers
7 *
8 *           +--------------+
9 *         B |1     ++    16| VCC
10 *         C |2           15| f
11 * LAMP TEST |3           14| g
12 *    BI/RBQ |4    7448   13| a
13 *       RBI |5           12| b
14 *         D |6           11| c
15 *         A |7           10| d
16 *       GND |8            9| e
17 *           +--------------+
18 *
19 *
20 *  Naming conventions follow National Semiconductor datasheet
21 *
22 */
23
24#ifndef NLD_7448_H_
25#define NLD_7448_H_
26
27#include "nl_base.h"
28
29#define TTL_7448(_name, _A0, _A1, _A2, _A3, _LTQ, _BIQ, _RBIQ)                      \
30      NET_REGISTER_DEV(TTL_7448, _name)                                               \
31      NET_CONNECT(_name, A, _A0)                                                  \
32      NET_CONNECT(_name, B, _A1)                                                  \
33      NET_CONNECT(_name, C, _A2)                                                  \
34      NET_CONNECT(_name, D, _A3)                                                  \
35      NET_CONNECT(_name, LTQ, _LTQ)                                               \
36      NET_CONNECT(_name, BIQ, _BIQ)                                               \
37      NET_CONNECT(_name, RBIQ, _RBIQ)
38
39#define TTL_7448_DIP(_name)                                                         \
40      NET_REGISTER_DEV(TTL_7448_DIP, _name)
41
42/*
43 * FIXME: Using truthtable is a lot slower than the explicit device
44 */
45#if (0 && USE_TRUTHTABLE)
46#include "nld_truthtable.h"
47
48NETLIB_TRUTHTABLE(7448, 7, 7, 0);
49#else
50
51NETLIB_NAMESPACE_DEVICES_START()
52
53NETLIB_SUBDEVICE(7448_sub,
54   ATTR_HOT void update_outputs(UINT8 v);
55   static const UINT8 tab7448[16][7];
56
57   logic_input_t m_A;
58   logic_input_t m_B;
59   logic_input_t m_C;
60   logic_input_t m_D;
61   logic_input_t m_RBIQ;
62
63   UINT8 m_state;
64
65   logic_output_t m_Q[7];  /* a .. g */
66
67);
68
69NETLIB_DEVICE(7448,
70public:
71   NETLIB_NAME(7448_sub) sub;
72
73   logic_input_t m_LTQ;
74   logic_input_t m_BIQ;
75);
76#endif
77
78NETLIB_DEVICE_DERIVED_PURE(7448_dip, 7448);
79
80NETLIB_NAMESPACE_DEVICES_END()
81
82#endif /* NLD_7448_H_ */
trunk/src/lib/netlist/devices/nld_7450.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7450.c
5 *
6 */
7
8#include "nld_7450.h"
9
10NETLIB_NAMESPACE_DEVICES_START()
11
12NETLIB_START(7450)
13{
14   register_input("A", m_A);
15   register_input("B", m_B);
16   register_input("C", m_C);
17   register_input("D", m_D);
18   register_output("Q", m_Q);
19}
20
21NETLIB_RESET(7450)
22{
23}
24
25NETLIB_UPDATE(7450)
26{
27   m_A.activate();
28   m_B.activate();
29   m_C.activate();
30   m_D.activate();
31   UINT8 t1 = INPLOGIC(m_A) & INPLOGIC(m_B);
32   UINT8 t2 = INPLOGIC(m_C) & INPLOGIC(m_D);
33
34   const netlist_time times[2] = { NLTIME_FROM_NS(22), NLTIME_FROM_NS(15) };
35
36   UINT8 res = 0;
37   if (t1 ^ 1)
38   {
39      if (t2 ^ 1)
40      {
41         res = 1;
42      }
43      else
44      {
45         m_A.inactivate();
46         m_B.inactivate();
47      }
48   } else {
49      if (t2 ^ 1)
50      {
51         m_C.inactivate();
52         m_D.inactivate();
53      }
54   }
55   OUTLOGIC(m_Q, res, times[1 - res]);// ? 22000 : 15000);
56}
57
58
59NETLIB_START(7450_dip)
60{
61   register_sub("1", m_1);
62   register_sub("2", m_2);
63
64   register_subalias("1", m_1.m_A);
65   register_subalias("2", m_2.m_A);
66   register_subalias("3", m_2.m_B);
67   register_subalias("4", m_2.m_C);
68   register_subalias("5", m_2.m_D);
69   register_subalias("6", m_2.m_Q);
70   //register_subalias("7",);  GND
71
72   register_subalias("8", m_1.m_Q);
73   register_subalias("9", m_1.m_C);
74   register_subalias("10", m_1.m_D);
75   //register_subalias("11", m_1.m_X1);
76   //register_subalias("12", m_1.m_X1Q);
77   register_subalias("13", m_1.m_B);
78   //register_subalias("14",);  VCC
79}
80
81NETLIB_UPDATE(7450_dip)
82{
83   /* only called during startup */
84   m_1.update_dev();
85   m_2.update_dev();
86}
87
88NETLIB_RESET(7450_dip)
89{
90   m_1.do_reset();
91   m_2.do_reset();
92}
93
94NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_7450.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7450.h
5 *
6 *  DM7450: DUAL 2-WIDE 2-INPUT AND-OR-INVERT GATES (ONE GATE EXPANDABLE)
7 *
8 *          +--------------+
9 *       1A |1     ++    14| VCC
10 *       2A |2           13| 1B
11 *       2B |3           12| 1XQ
12 *       2C |4    7450   11| 1X
13 *       2D |5           10| 1D
14 *       2Y |6            9| 1C
15 *      GND |7            8| 1Y
16 *          +--------------+
17 *                  _________________
18 *              Y = (A & B) | (C & D)
19 *
20 *  Naming conventions follow Texas Instruments datasheet
21 *
22 */
23
24#ifndef NLD_7450_H_
25#define NLD_7450_H_
26
27#include "nld_signal.h"
28
29#define TTL_7450_ANDORINVERT(_name, _I1, _I2, _I3, _I4)                             \
30      NET_REGISTER_DEV(TTL_7450_ANDORINVERT, _name)                                               \
31      NET_CONNECT(_name, A, _I1)                                                  \
32      NET_CONNECT(_name, B, _I2)                                                  \
33      NET_CONNECT(_name, C, _I3)                                                  \
34      NET_CONNECT(_name, D, _I4)
35
36#define TTL_7450_DIP(_name)                                                         \
37      NET_REGISTER_DEV(TTL_7450_DIP, _name)
38
39NETLIB_NAMESPACE_DEVICES_START()
40
41NETLIB_DEVICE(7450,
42public:
43   logic_input_t m_A;
44   logic_input_t m_B;
45   logic_input_t m_C;
46   logic_input_t m_D;
47   logic_output_t m_Q;
48);
49
50NETLIB_DEVICE(7450_dip,
51
52   NETLIB_NAME(7450) m_1;
53   NETLIB_NAME(7450) m_2;
54);
55
56NETLIB_NAMESPACE_DEVICES_END()
57
58#endif /* NLD_7450_H_ */
trunk/src/lib/netlist/devices/nld_7474.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7474.c
5 *
6 */
7
8#include "nld_7474.h"
9
10NETLIB_NAMESPACE_DEVICES_START()
11
12ATTR_HOT inline void NETLIB_NAME(7474sub)::newstate(const UINT8 stateQ, const UINT8 stateQQ)
13{
14   // 0: High-to-low 40 ns, 1: Low-to-high 25 ns
15   const netlist_time delay[2] = { NLTIME_FROM_NS(40), NLTIME_FROM_NS(25) };
16   OUTLOGIC(m_Q, stateQ, delay[stateQ]);
17   OUTLOGIC(m_QQ, stateQQ, delay[stateQQ]);
18}
19
20NETLIB_UPDATE(7474sub)
21{
22   //if (INP_LH(m_CLK))
23   {
24      newstate(m_nextD, !m_nextD);
25      m_CLK.inactivate();
26   }
27}
28
29NETLIB_UPDATE(7474)
30{
31   if (INPLOGIC(m_PREQ) && INPLOGIC(m_CLRQ))
32   {
33      m_D.activate();
34      sub.m_nextD = INPLOGIC(m_D);
35      sub.m_CLK.activate_lh();
36   }
37   else if (!INPLOGIC(m_PREQ))
38   {
39      sub.newstate(1, 0);
40      sub.m_CLK.inactivate();
41      m_D.inactivate();
42   }
43   else if (!INPLOGIC(m_CLRQ))
44   {
45      sub.newstate(0, 1);
46      sub.m_CLK.inactivate();
47      m_D.inactivate();
48   }
49   else
50   {
51      sub.newstate(1, 1);
52      sub.m_CLK.inactivate();
53      m_D.inactivate();
54   }
55}
56
57NETLIB_START(7474)
58{
59   register_sub("sub", sub);
60
61   register_subalias("CLK",    sub.m_CLK);
62   register_input("D",         m_D);
63   register_input("CLRQ",      m_CLRQ);
64   register_input("PREQ",      m_PREQ);
65
66   register_subalias("Q",      sub.m_Q);
67   register_subalias("QQ",     sub.m_QQ);
68
69}
70
71NETLIB_RESET(7474)
72{
73   sub.do_reset();
74}
75
76NETLIB_START(7474sub)
77{
78   register_input("CLK",  m_CLK);
79
80   register_output("Q",   m_Q);
81   register_output("QQ",  m_QQ);
82
83   save(NLNAME(m_nextD));
84}
85
86NETLIB_RESET(7474sub)
87{
88   m_CLK.set_state(logic_t::STATE_INP_LH);
89
90   m_nextD = 0;
91}
92
93NETLIB_START(7474_dip)
94{
95   register_sub("1", m_1);
96   register_sub("2", m_2);
97
98   register_subalias("1", m_1.m_CLRQ);
99   register_subalias("2", m_1.m_D);
100   register_subalias("3", m_1.sub.m_CLK);
101   register_subalias("4", m_1.m_PREQ);
102   register_subalias("5", m_1.sub.m_Q);
103   register_subalias("6", m_1.sub.m_QQ);
104   // register_subalias("7", ); ==> GND
105
106   register_subalias("8", m_2.sub.m_QQ);
107   register_subalias("9", m_2.sub.m_Q);
108   register_subalias("10", m_2.m_PREQ);
109   register_subalias("11", m_2.sub.m_CLK);
110   register_subalias("12", m_2.m_D);
111   register_subalias("13", m_2.m_CLRQ);
112   // register_subalias("14", ); ==> VCC
113}
114
115NETLIB_RESET(7474_dip)
116{
117   m_1.do_reset();
118   m_2.do_reset();
119}
120
121NETLIB_UPDATE(7474_dip)
122{
123   m_1.update_dev();
124   m_2.update_dev();
125}
126
127NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_7474.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7474.h
5 *
6 *  DM7474: Dual Positive-Edge-Triggered D Flip-Flops
7 *          with Preset, Clear and Complementary Outputs
8 *
9 *          +--------------+
10 *     CLR1 |1     ++    14| VCC
11 *       D1 |2           13| CLR2
12 *     CLK1 |3           12| D2
13 *      PR1 |4    7474   11| CLK2
14 *       Q1 |5           10| PR2
15 *      Q1Q |6            9| Q2
16 *      GND |7            8| Q2Q
17 *          +--------------+
18 *
19 *          +-----+-----+-----+---++---+-----+
20 *          | PR  | CLR | CLK | D || Q | QQ  |
21 *          +=====+=====+=====+===++===+=====+
22 *          |  0  |  1  |  X  | X || 1 |  0  |
23 *          |  1  |  0  |  X  | X || 0 |  1  |
24 *          |  0  |  0  |  X  | X || 1 |  1  | (*)
25 *          |  1  |  1  |  R  | 1 || 1 |  0  |
26 *          |  1  |  1  |  R  | 0 || 0 |  1  |
27 *          |  1  |  1  |  0  | X || Q0| Q0Q |
28 *          +-----+-----+-----+---++---+-----+
29 *
30 *  (*) This configuration is not stable, i.e. it will not persist
31 *  when either the preset and or clear inputs return to their inactive (high) level
32 *
33 *  Q0 The output logic level of Q before the indicated input conditions were established
34 *
35 *  R:  0 --> 1
36 *
37 *  Naming conventions follow National Semiconductor datasheet
38 *
39 *  FIXME: Check that (*) is emulated properly
40 */
41
42#ifndef NLD_7474_H_
43#define NLD_7474_H_
44
45#include "nld_signal.h"
46
47#define TTL_7474(_name, _CLK, _D, _CLRQ, _PREQ)                                     \
48      NET_REGISTER_DEV(TTL_7474, _name)                                               \
49      NET_CONNECT(_name, CLK, _CLK)                                               \
50      NET_CONNECT(_name, D,  _D)                                                  \
51      NET_CONNECT(_name, CLRQ,  _CLRQ)                                            \
52      NET_CONNECT(_name, PREQ,  _PREQ)
53
54#define TTL_7474_DIP(_name)                                                         \
55      NET_REGISTER_DEV(TTL_7474_DIP, _name)
56
57NETLIB_NAMESPACE_DEVICES_START()
58
59NETLIB_SUBDEVICE(7474sub,
60   logic_input_t m_CLK;
61
62   INT8 m_nextD;
63   logic_output_t m_Q;
64   logic_output_t m_QQ;
65
66   ATTR_HOT inline void newstate(const UINT8 stateQ, const UINT8 stateQQ);
67);
68
69NETLIB_DEVICE(7474,
70public:
71   NETLIB_NAME(7474sub) sub;
72
73   logic_input_t m_D;
74   logic_input_t m_CLRQ;
75   logic_input_t m_PREQ;
76);
77
78NETLIB_DEVICE(7474_dip,
79
80   NETLIB_NAME(7474) m_1;
81   NETLIB_NAME(7474) m_2;
82);
83
84NETLIB_NAMESPACE_DEVICES_END()
85
86#endif /* NLD_7474_H_ */
trunk/src/lib/netlist/devices/nld_7483.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7483.c
5 *
6 */
7
8#include "nld_7483.h"
9
10NETLIB_NAMESPACE_DEVICES_START()
11
12NETLIB_START(7483)
13{
14   register_input("A1", m_A1);
15   register_input("A2", m_A2);
16   register_input("A3", m_A3);
17   register_input("A4", m_A4);
18   register_input("B1", m_B1);
19   register_input("B2", m_B2);
20   register_input("B3", m_B3);
21   register_input("B4", m_B4);
22   register_input("C0", m_C0);
23
24   register_output("S1", m_S1);
25   register_output("S2", m_S2);
26   register_output("S3", m_S3);
27   register_output("S4", m_S4);
28   register_output("C4", m_C4);
29
30   save(NLNAME(m_lastr));
31}
32
33NETLIB_RESET(7483)
34{
35   m_lastr = 0;
36}
37
38NETLIB_UPDATE(7483)
39{
40   UINT8 a = (INPLOGIC(m_A1) << 0) | (INPLOGIC(m_A2) << 1) | (INPLOGIC(m_A3) << 2) | (INPLOGIC(m_A4) << 3);
41   UINT8 b = (INPLOGIC(m_B1) << 0) | (INPLOGIC(m_B2) << 1) | (INPLOGIC(m_B3) << 2) | (INPLOGIC(m_B4) << 3);
42
43   UINT8 r = a + b + INPLOGIC(m_C0);
44
45   if (r != m_lastr)
46   {
47      m_lastr = r;
48      OUTLOGIC(m_S1, (r >> 0) & 1, NLTIME_FROM_NS(23));
49      OUTLOGIC(m_S2, (r >> 1) & 1, NLTIME_FROM_NS(23));
50      OUTLOGIC(m_S3, (r >> 2) & 1, NLTIME_FROM_NS(23));
51      OUTLOGIC(m_S4, (r >> 3) & 1, NLTIME_FROM_NS(23));
52      OUTLOGIC(m_C4, (r >> 4) & 1, NLTIME_FROM_NS(23));
53   }
54}
55
56NETLIB_START(7483_dip)
57{
58   NETLIB_NAME(7483)::start();
59   register_subalias("1", m_A4);
60   register_subalias("2", m_S3);
61   register_subalias("3", m_A3);
62   register_subalias("4", m_B3);
63   // register_subalias("5", ); --> VCC
64   register_subalias("6", m_S2);
65   register_subalias("7", m_B2);
66   register_subalias("8", m_A2);
67
68   register_subalias("9", m_S1);
69   register_subalias("10", m_A1);
70   register_subalias("11", m_B1);
71   // register_subalias("12", ); --> GND
72   register_subalias("13", m_C0);
73   register_subalias("14", m_C4);
74   register_subalias("15", m_S4);
75   register_subalias("16", m_B4);
76
77}
78
79NETLIB_UPDATE(7483_dip)
80{
81   NETLIB_NAME(7483)::update();
82}
83
84NETLIB_RESET(7483_dip)
85{
86   NETLIB_NAME(7483)::reset();
87}
88
89NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_7483.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7483.h
5 *
6 *  DM7483: 4-Bit Binary Adder with Fast Carry
7 *
8 *          +--------------+
9 *       A4 |1     ++    16| B4
10 *       S3 |2           15| S4
11 *       A3 |3           14| C4
12 *       B3 |4    7483   13| C0
13 *      VCC |5           12| GND
14 *       S2 |6           11| B1
15 *       B2 |7           10| A1
16 *       A2 |8            9| S1
17 *          +--------------+
18 *
19 *          S = (A + B + C0) & 0x0f
20 *
21 *          C4 = (A + B + C) > 15 ? 1 : 0
22 *
23 *  Naming conventions follow Fairchild Semiconductor datasheet
24 *
25 */
26
27#ifndef NLD_7483_H_
28#define NLD_7483_H_
29
30#include "nl_base.h"
31
32#define TTL_7483(_name, _A1, _A2, _A3, _A4, _B1, _B2, _B3, _B4, _CI)                \
33      NET_REGISTER_DEV(TTL_7483, _name)                                               \
34      NET_CONNECT(_name, A1, _A1)                                                 \
35      NET_CONNECT(_name, A2, _A2)                                                 \
36      NET_CONNECT(_name, A3, _A3)                                                 \
37      NET_CONNECT(_name, A4, _A4)                                                 \
38      NET_CONNECT(_name, B1, _B1)                                                 \
39      NET_CONNECT(_name, B2, _B2)                                                 \
40      NET_CONNECT(_name, B3, _B3)                                                 \
41      NET_CONNECT(_name, B4, _B4)                                                 \
42      NET_CONNECT(_name, C0, _CI)
43
44#define TTL_7483_DIP(_name)                                                         \
45      NET_REGISTER_DEV(TTL_7483_DIP, _name)
46
47NETLIB_NAMESPACE_DEVICES_START()
48
49NETLIB_DEVICE(7483,
50   logic_input_t m_C0;
51   logic_input_t m_A1;
52   logic_input_t m_A2;
53   logic_input_t m_A3;
54   logic_input_t m_A4;
55   logic_input_t m_B1;
56   logic_input_t m_B2;
57   logic_input_t m_B3;
58   logic_input_t m_B4;
59
60   UINT8 m_lastr;
61
62   logic_output_t m_S1;
63   logic_output_t m_S2;
64   logic_output_t m_S3;
65   logic_output_t m_S4;
66   logic_output_t m_C4;
67
68);
69
70NETLIB_DEVICE_DERIVED_PURE(7483_dip, 7483);
71
72NETLIB_NAMESPACE_DEVICES_END()
73
74#endif /* NLD_7483_H_ */
trunk/src/lib/netlist/devices/nld_7486.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7486.c
5 *
6 */
7
8#include "nld_7486.h"
9
10NETLIB_NAMESPACE_DEVICES_START()
11
12#if (USE_TRUTHTABLE)
13nld_7486::truthtable_t nld_7486::m_ttbl;
14const char *nld_7486::m_desc[] = {
15      "A , B | Q ",
16      "0,0|0|15",
17      "0,1|1|22",
18      "1,0|1|22",
19      "1,1|0|15",
20      ""
21};
22#else
23NETLIB_START(7486)
24{
25   register_input("A", m_I[0]);
26   register_input("B", m_I[1]);
27   register_output("Q", m_Q[0]);
28
29   save(NLNAME(m_active));
30}
31
32NETLIB_RESET(7486)
33{
34   m_active = 1;
35}
36
37NETLIB_UPDATE(7486)
38{
39   const netlist_time delay[2] = { NLTIME_FROM_NS(15), NLTIME_FROM_NS(22) };
40
41   UINT8 t = INPLOGIC(m_I[0]) ^ INPLOGIC(m_I[1]);
42   OUTLOGIC(m_Q[0], t, delay[t]);
43}
44
45ATTR_HOT void NETLIB_NAME(7486)::inc_active()
46{
47   const netlist_time delay[2] = { NLTIME_FROM_NS(15), NLTIME_FROM_NS(22) };
48   nl_assert(netlist().use_deactivate());
49   if (++m_active == 1)
50   {
51      m_I[0].activate();
52      m_I[1].activate();
53
54      netlist_time mt = this->m_I[0].net().time();
55      if (this->m_I[1].net().time() > mt)
56         mt = this->m_I[1].net().time();
57
58      UINT8 t = INPLOGIC(m_I[0]) ^ INPLOGIC(m_I[1]);
59      m_Q[0].net().set_Q_time(t, mt + delay[t]);
60   }
61}
62
63ATTR_HOT void NETLIB_NAME(7486)::dec_active()
64{
65#if 1
66   nl_assert(netlist().use_deactivate());
67   if (--m_active == 0)
68   {
69      m_I[0].inactivate();
70      m_I[1].inactivate();
71   }
72#endif
73}
74#endif
75
76NETLIB_START(7486_dip)
77{
78   register_sub("1", m_1);
79   register_sub("2", m_2);
80   register_sub("3", m_3);
81   register_sub("4", m_4);
82
83   register_subalias("1", m_1.m_I[0]);
84   register_subalias("2", m_1.m_I[1]);
85   register_subalias("3", m_1.m_Q[0]);
86
87   register_subalias("4", m_2.m_I[0]);
88   register_subalias("5", m_2.m_I[1]);
89   register_subalias("6", m_2.m_Q[0]);
90
91   register_subalias("9", m_3.m_I[0]);
92   register_subalias("10", m_3.m_I[1]);
93   register_subalias("8", m_3.m_Q[0]);
94
95   register_subalias("12", m_4.m_I[0]);
96   register_subalias("13", m_4.m_I[1]);
97   register_subalias("11", m_4.m_Q[0]);
98}
99
100NETLIB_UPDATE(7486_dip)
101{
102   /* only called during startup */
103   m_1.update_dev();
104   m_2.update_dev();
105   m_3.update_dev();
106   m_4.update_dev();
107}
108
109NETLIB_RESET(7486_dip)
110{
111   m_1.do_reset();
112   m_2.do_reset();
113   m_3.do_reset();
114   m_4.do_reset();
115}
116
117NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_7486.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7486.h
5 *
6 *  DM7486: Quad 2-Input Quad 2-Input Exclusive-OR Gates
7 *
8 *          +--------------+
9 *       A1 |1     ++    14| VCC
10 *       B1 |2           13| B4
11 *       Y1 |3           12| A4
12 *       A2 |4    7486   11| Y4
13 *       B2 |5           10| B3
14 *       Y2 |6            9| A3
15 *      GND |7            8| Y3
16 *          +--------------+
17 *
18 *             Y = A+B
19 *          +---+---++---+
20 *          | A | B || Y |
21 *          +===+===++===+
22 *          | 0 | 0 || 0 |
23 *          | 0 | 1 || 1 |
24 *          | 1 | 0 || 1 |
25 *          | 1 | 1 || 0 |
26 *          +---+---++---+
27 *
28 *  Naming conventions follow National Semiconductor datasheet
29 *
30 */
31
32#ifndef NLD_7486_H_
33#define NLD_7486_H_
34
35#include "nld_signal.h"
36#include "nld_truthtable.h"
37
38#define TTL_7486_XOR(_name, _A, _B)                                                 \
39      NET_REGISTER_DEV(TTL_7486_XOR, _name)                                               \
40      NET_CONNECT(_name, A, _A)                                                   \
41      NET_CONNECT(_name, B, _B)
42
43
44#define TTL_7486_DIP(_name)                                                         \
45      NET_REGISTER_DEV(TTL_7486_DIP, _name)
46
47NETLIB_NAMESPACE_DEVICES_START()
48
49#if (USE_TRUTHTABLE)
50NETLIB_TRUTHTABLE(7486, 2, 1, 0);
51#else
52NETLIB_DEVICE(7486,
53public:
54      netlist_logic_input_t m_I[2];
55      netlist_logic_output_t m_Q[1];
56
57      ATTR_HOT void inc_active();
58      ATTR_HOT void dec_active();
59      int m_active;
60);
61#endif
62
63NETLIB_DEVICE(7486_dip,
64
65   NETLIB_NAME(7486) m_1;
66   NETLIB_NAME(7486) m_2;
67   NETLIB_NAME(7486) m_3;
68   NETLIB_NAME(7486) m_4;
69);
70
71NETLIB_NAMESPACE_DEVICES_END()
72
73#endif /* NLD_7486_H_ */
trunk/src/lib/netlist/devices/nld_7490.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7490.c
5 *
6 */
7
8#include "nld_7490.h"
9
10NETLIB_NAMESPACE_DEVICES_START()
11
12NETLIB_START(7490)
13{
14   register_input("A", m_A);
15   register_input("B", m_B);
16   register_input("R1",  m_R1);
17   register_input("R2",  m_R2);
18   register_input("R91", m_R91);
19   register_input("R92", m_R92);
20
21   register_output("QA", m_Q[0]);
22   register_output("QB", m_Q[1]);
23   register_output("QC", m_Q[2]);
24   register_output("QD", m_Q[3]);
25
26   save(NLNAME(m_cnt));
27   save(NLNAME(m_last_A));
28   save(NLNAME(m_last_B));
29
30}
31
32NETLIB_RESET(7490)
33{
34   m_cnt = 0;
35   m_last_A = 0;
36   m_last_B = 0;
37}
38
39static const netlist_time delay[4] =
40{
41      NLTIME_FROM_NS(18),
42      NLTIME_FROM_NS(36) - NLTIME_FROM_NS(18),
43      NLTIME_FROM_NS(54) - NLTIME_FROM_NS(18),
44      NLTIME_FROM_NS(72) - NLTIME_FROM_NS(18)};
45
46NETLIB_UPDATE(7490)
47{
48   const netlist_sig_t new_A = INPLOGIC(m_A);
49   const netlist_sig_t new_B = INPLOGIC(m_B);
50
51   if (INPLOGIC(m_R91) & INPLOGIC(m_R92))
52   {
53      m_cnt = 9;
54      update_outputs();
55   }
56   else if (INPLOGIC(m_R1) & INPLOGIC(m_R2))
57   {
58      m_cnt = 0;
59      update_outputs();
60   }
61   else
62   {
63      if (m_last_A && !new_A)  // High - Low
64      {
65         m_cnt ^= 1;
66         OUTLOGIC(m_Q[0], m_cnt & 1, delay[0]);
67      }
68      if (m_last_B && !new_B)  // High - Low
69      {
70         m_cnt += 2;
71         if (m_cnt >= 10)
72            m_cnt &= 1; /* Output A is not reset! */
73         update_outputs();
74      }
75   }
76   m_last_A = new_A;
77   m_last_B = new_B;
78}
79
80NETLIB_FUNC_VOID(7490, update_outputs, (void))
81{
82   for (int i=0; i<4; i++)
83      OUTLOGIC(m_Q[i], (m_cnt >> i) & 1, delay[i]);
84}
85
86NETLIB_START(7490_dip)
87{
88   NETLIB_NAME(7490)::start();
89   register_subalias("1", m_B);
90   register_subalias("2", m_R1);
91   register_subalias("3", m_R2);
92
93   // register_subalias("4", ); --> NC
94   // register_subalias("5", ); --> VCC
95   register_subalias("6", m_R91);
96   register_subalias("7", m_R92);
97
98   register_subalias("8", m_Q[2]);
99   register_subalias("9", m_Q[1]);
100   // register_subalias("10", ); --> GND
101   register_subalias("11", m_Q[3]);
102   register_subalias("12", m_Q[0]);
103   // register_subalias("13", ); --> NC
104   register_subalias("14", m_A);
105
106}
107
108NETLIB_UPDATE(7490_dip)
109{
110   NETLIB_NAME(7490)::update();
111}
112
113NETLIB_RESET(7490_dip)
114{
115   NETLIB_NAME(7490)::reset();
116}
117
118NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_7490.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7490.h
5 *
6 *  DM7490: Decade Counters
7 *
8 *          +--------------+
9 *        B |1     ++    14| A
10 *      R01 |2           13| NC
11 *      R02 |3           12| QA
12 *       NC |4    7490   11| QD
13 *      VCC |5           10| GND
14 *      R91 |6            9| QB
15 *      R92 |7            8| QC
16 *          +--------------+
17 *
18 *          Counter Sequence
19 *
20 *          +-------++----+----+----+----+
21 *          | COUNT || QD | QC | QB | QA |
22 *          +=======++====+====+====+====+
23 *          |    0  ||  0 |  0 |  0 |  0 |
24 *          |    1  ||  0 |  0 |  0 |  1 |
25 *          |    2  ||  0 |  0 |  1 |  0 |
26 *          |    3  ||  0 |  0 |  1 |  1 |
27 *          |    4  ||  0 |  1 |  0 |  0 |
28 *          |    5  ||  0 |  1 |  0 |  1 |
29 *          |    6  ||  0 |  1 |  1 |  0 |
30 *          |    7  ||  0 |  1 |  1 |  1 |
31 *          |    8  ||  1 |  0 |  0 |  0 |
32 *          |    9  ||  1 |  0 |  0 |  1 |
33 *          +-------++----+----+----+----+
34 *
35 *          Note A Output QA is connected to input B for BCD count
36 *
37 *          Reset Count Function table
38 *
39 *          +-----+-----+-----+-----++----+----+----+----+
40 *          | R01 | R02 | R91 | R92 || QD | QC | QB | QA |
41 *          +=====+=====+=====+=====++====+====+====+====+
42 *          |  1  |  1  |  0  |  X  ||  0 |  0 |  0 |  0 |
43 *          |  1  |  1  |  X  |  0  ||  0 |  0 |  0 |  0 |
44 *          |  X  |  X  |  1  |  1  ||  1 |  0 |  0 |  1 |
45 *          |  X  |  0  |  X  |  0  ||       COUNT       |
46 *          |  0  |  X  |  0  |  X  ||       COUNT       |
47 *          |  0  |  X  |  X  |  0  ||       COUNT       |
48 *          |  X  |  0  |  0  |  X  ||       COUNT       |
49 *          +-----+-----+-----+-----++----+----+----+----+
50 *
51 *  Naming conventions follow National Semiconductor datasheet
52 *
53 */
54
55#ifndef NLD_7490_H_
56#define NLD_7490_H_
57
58#include "nl_base.h"
59
60#define TTL_7490(_name, _A, _B, _R1, _R2, _R91, _R92)                               \
61      NET_REGISTER_DEV(TTL_7490, _name)                                               \
62      NET_CONNECT(_name, A, _A)                                                   \
63      NET_CONNECT(_name, B, _B)                                                   \
64      NET_CONNECT(_name, R1,  _R1)                                                \
65      NET_CONNECT(_name, R2,  _R2)                                                \
66      NET_CONNECT(_name, R91, _R91)                                               \
67      NET_CONNECT(_name, R92, _R92)
68
69#define TTL_7490_DIP(_name)                                                         \
70      NET_REGISTER_DEV(TTL_7490_DIP, _name)
71
72NETLIB_NAMESPACE_DEVICES_START()
73
74NETLIB_DEVICE(7490,
75   ATTR_HOT void update_outputs();
76
77   logic_input_t m_R1;
78   logic_input_t m_R2;
79   logic_input_t m_R91;
80   logic_input_t m_R92;
81   logic_input_t m_A;
82   logic_input_t m_B;
83
84   UINT8 m_cnt;
85   UINT8 m_last_A;
86   UINT8 m_last_B;
87
88   logic_output_t m_Q[4];
89);
90
91NETLIB_DEVICE_DERIVED_PURE(7490_dip, 7490);
92
93NETLIB_NAMESPACE_DEVICES_END()
94
95#endif /* NLD_7490_H_ */
trunk/src/lib/netlist/devices/nld_7493.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7493.c
5 *
6 */
7
8#include "nld_7493.h"
9#include "nl_setup.h"
10
11NETLIB_NAMESPACE_DEVICES_START()
12
13NETLIB_START(7493)
14{
15   register_sub("A", A);
16   register_sub("B", B);
17   register_sub("C", C);
18   register_sub("D", D);
19
20   register_subalias("CLKA", A.m_I);
21   register_subalias("CLKB", B.m_I);
22   register_input("R1",  m_R1);
23   register_input("R2",  m_R2);
24
25   register_subalias("QA", A.m_Q);
26   register_subalias("QB", B.m_Q);
27   register_subalias("QC", C.m_Q);
28   register_subalias("QD", D.m_Q);
29
30   connect_late(C.m_I, B.m_Q);
31   connect_late(D.m_I, C.m_Q);
32}
33
34NETLIB_RESET(7493)
35{
36   A.do_reset();
37   B.do_reset();
38   C.do_reset();
39   D.do_reset();
40}
41
42NETLIB_START(7493ff)
43{
44   register_input("CLK", m_I);
45   register_output("Q", m_Q);
46
47   save(NLNAME(m_reset));
48   save(NLNAME(m_state));
49}
50
51NETLIB_RESET(7493ff)
52{
53   m_reset = 1;
54   m_state = 0;
55   m_I.set_state(logic_t::STATE_INP_HL);
56}
57
58NETLIB_UPDATE(7493ff)
59{
60   const netlist_time out_delay = NLTIME_FROM_NS(18);
61   if (m_reset != 0)
62   {
63      m_state ^= 1;
64      OUTLOGIC(m_Q, m_state, out_delay);
65   }
66}
67
68NETLIB_UPDATE(7493)
69{
70   const netlist_sig_t r = INPLOGIC(m_R1) & INPLOGIC(m_R2);
71
72   if (r)
73   {
74      A.m_I.inactivate();
75      B.m_I.inactivate();
76      OUTLOGIC(A.m_Q, 0, NLTIME_FROM_NS(40));
77      OUTLOGIC(B.m_Q, 0, NLTIME_FROM_NS(40));
78      OUTLOGIC(C.m_Q, 0, NLTIME_FROM_NS(40));
79      OUTLOGIC(D.m_Q, 0, NLTIME_FROM_NS(40));
80      A.m_reset = B.m_reset = C.m_reset = D.m_reset = 0;
81      A.m_state = B.m_state = C.m_state = D.m_state = 0;
82   }
83   else
84   {
85      A.m_I.activate_hl();
86      B.m_I.activate_hl();
87      A.m_reset = B.m_reset = C.m_reset = D.m_reset = 1;
88   }
89}
90
91NETLIB_START(7493_dip)
92{
93   NETLIB_NAME(7493)::start();
94
95   register_subalias("1", B.m_I);
96   register_subalias("2", m_R1);
97   register_subalias("3", m_R2);
98
99   // register_subalias("4", ); --> NC
100   // register_subalias("5", ); --> VCC
101   // register_subalias("6", ); --> NC
102   // register_subalias("7", ); --> NC
103
104   register_subalias("8", C.m_Q);
105   register_subalias("9", B.m_Q);
106   // register_subalias("10", ); --> GND
107   register_subalias("11", D.m_Q);
108   register_subalias("12", A.m_Q);
109   // register_subalias("13", ); --> NC
110   register_subalias("14", A.m_I);
111}
112
113
114NETLIB_UPDATE(7493_dip)
115{
116   NETLIB_NAME(7493)::update();
117}
118
119NETLIB_RESET(7493_dip)
120{
121   NETLIB_NAME(7493)::reset();
122}
123
124NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_7493.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_7493.h
5 *
6 *  DM7493: Binary Counters
7 *
8 *          +--------------+
9 *        B |1     ++    14| A
10 *      R01 |2           13| NC
11 *      R02 |3           12| QA
12 *       NC |4    7493   11| QD
13 *      VCC |5           10| GND
14 *       NC |6            9| QB
15 *       NC |7            8| QC
16 *          +--------------+
17 *
18 *          Counter Sequence
19 *
20 *          +-------++----+----+----+----+
21 *          | COUNT || QD | QC | QB | QA |
22 *          +=======++====+====+====+====+
23 *          |    0  ||  0 |  0 |  0 |  0 |
24 *          |    1  ||  0 |  0 |  0 |  1 |
25 *          |    2  ||  0 |  0 |  1 |  0 |
26 *          |    3  ||  0 |  0 |  1 |  1 |
27 *          |    4  ||  0 |  1 |  0 |  0 |
28 *          |    5  ||  0 |  1 |  0 |  1 |
29 *          |    6  ||  0 |  1 |  1 |  0 |
30 *          |    7  ||  0 |  1 |  1 |  1 |
31 *          |    8  ||  1 |  0 |  0 |  0 |
32 *          |    9  ||  1 |  0 |  0 |  1 |
33 *          |   10  ||  1 |  0 |  1 |  0 |
34 *          |   11  ||  1 |  0 |  1 |  1 |
35 *          |   12  ||  1 |  1 |  0 |  0 |
36 *          |   13  ||  1 |  1 |  0 |  1 |
37 *          |   14  ||  1 |  1 |  1 |  0 |
38 *          |   15  ||  1 |  1 |  1 |  1 |
39 *          +-------++----+----+----+----+
40 *
41 *          Note C Output QA is connected to input B
42 *
43 *          Reset Count Function table
44 *
45 *          +-----+-----++----+----+----+----+
46 *          | R01 | R02 || QD | QC | QB | QA |
47 *          +=====+=====++====+====+====+====+
48 *          |  1  |  1  ||  0 |  0 |  0 |  0 |
49 *          |  0  |  X  ||       COUNT       |
50 *          |  X  |  0  ||       COUNT       |
51 *          +-----+-----++----+----+----+----+
52 *
53 *  Naming conventions follow National Semiconductor datasheet
54 *
55 */
56
57#ifndef NLD_7493_H_
58#define NLD_7493_H_
59
60#include "nl_base.h"
61
62#define TTL_7493(_name, _CLKA, _CLKB, _R1, _R2)                                     \
63      NET_REGISTER_DEV(TTL_7493, _name)                                               \
64      NET_CONNECT(_name, CLKA, _CLKA)                                             \
65      NET_CONNECT(_name, CLKB, _CLKB)                                             \
66      NET_CONNECT(_name, R1,  _R1)                                                \
67      NET_CONNECT(_name, R2,  _R2)
68
69#define TTL_7493_DIP(_name)                                                         \
70      NET_REGISTER_DEV(TTL_7493_DIP, _name)
71
72NETLIB_NAMESPACE_DEVICES_START()
73
74NETLIB_SUBDEVICE(7493ff,
75   logic_input_t m_I;
76   logic_output_t m_Q;
77
78   UINT8 m_reset;
79   UINT8 m_state;
80);
81
82NETLIB_DEVICE(7493,
83   logic_input_t m_R1;
84   logic_input_t m_R2;
85
86   NETLIB_NAME(7493ff) A;
87   NETLIB_NAME(7493ff) B;
88   NETLIB_NAME(7493ff) C;
89   NETLIB_NAME(7493ff) D;
90);
91
92NETLIB_DEVICE_DERIVED_PURE(7493_dip, 7493);
93
94NETLIB_NAMESPACE_DEVICES_END()
95
96
97#endif /* NLD_7493_H_ */
trunk/src/lib/netlist/devices/nld_74ls629.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_SN74LS629.c
5 *
6 */
7
8/*
9 * The 74LS624 series are constant current based VCOs.  The Freq Control voltage
10 * modulates the current source.  The current is created from Rext, which is
11 * internally fixed at 600 ohms for all devices except the 74LS628 which has
12 * external connections.  The current source linearly discharges the cap voltage.
13 * The cap starts with 0V charge across it.  One side is connected to a fixed voltage
14 * bias circuit.  The other side is charged negatively from the current source until
15 * a certain low threshold is reached.  Once this threshold is reached, the output
16 * toggles state and the pins on the cap reverse in respect to the charge/bias hookup.
17 * This starts the one side of the cap to be at bias, and the other side of the cap is
18 * now at bias + the charge on the cap which is bias - threshold.
19 * Y = 0;  CX1 = bias;    CX2 = charge
20 * Y = 1;  CX1 = charge;  CX2 = bias
21 * The Range voltage adjusts the threshold voltage.  The higher the Range voltage,
22 * the lower the threshold voltage, the longer the cap can charge, the lower the frequency.
23 *
24 * In a perfect world it would work like this:
25 * The current is based on the mysterious Rext mentioned in the data sheet.
26 * I = (VfreqControl  * 20k/90k) / Rext
27 * where Rext = 600 ohms or external Rext on a 74LS628
28 * The Freq Control has an input impedance of approximately 90k, so any input resistance
29 * connected to the Freq Control pin works as a voltage divider.
30 * I = (VfreqControl * 20k/(90k + RfreqControlIn)) / Rext
31 * That gives us a change in voltage on the cap of
32 * dV = I / sampleRate / C_inFarads
33 *
34 * Unfortunately the chip does not behave linearly do to internal interactions,
35 * so I have just worked out the formula (using zunzun.com) of FreqControl and
36 * range to frequency out for a fixed cap value of 0.1uf.  Other cap values can just
37 * scale from that.  From the freq, we calculate the time of 1/2 cycle using 1/Freq/2.
38 * Then just use that to toggle a waveform.
39 */
40
41
42#include "nld_74ls629.h"
43#include "nl_setup.h"
44
45NETLIB_NAMESPACE_DEVICES_START()
46
47NETLIB_START(SN74LS629clk)
48{
49   register_input("FB",    m_FB);
50   register_output("Y",    m_Y);
51
52   connect_late(m_FB, m_Y);
53
54   reset();
55
56   save(NLNAME(m_enableq));
57   save(NLNAME(m_inc));
58   save(NLNAME(m_out));
59}
60
61NETLIB_RESET(SN74LS629clk)
62{
63   m_enableq = 1;
64   m_out = 0;
65   m_inc = netlist_time::zero;
66}
67
68NETLIB_UPDATE(SN74LS629clk)
69{
70   if (!m_enableq)
71   {
72      m_out = m_out ^ 1;
73      OUTLOGIC(m_Y, m_out, m_inc);
74   }
75   else
76   {
77      OUTLOGIC(m_Y, 1, m_inc);
78   }
79}
80
81NETLIB_START(SN74LS629)
82{
83   register_sub("OSC", m_clock);
84   register_sub("R_FC", m_R_FC);
85   register_sub("R_RNG", m_R_RNG);
86
87   register_input("ENQ", m_ENQ);
88   register_input("RNG",    m_RNG);
89   register_input("FC",     m_FC);
90   register_subalias("GND",    m_R_FC.m_N);
91
92   connect_late(m_FC, m_R_FC.m_P);
93   connect_late(m_RNG, m_R_RNG.m_P);
94   connect_late(m_R_FC.m_N, m_R_RNG.m_N);
95
96   register_subalias("Y", m_clock.m_Y);
97   register_param("CAP", m_CAP, 1e-6);
98}
99
100NETLIB_RESET(SN74LS629)
101{
102   m_R_FC.set_R(90000.0);
103   m_R_RNG.set_R(90000.0);
104   m_clock.reset();
105}
106
107NETLIB_UPDATE(SN74LS629)
108{
109   {
110      // recompute
111      nl_double  freq;
112      nl_double  v_freq_2, v_freq_3, v_freq_4;
113      nl_double  v_freq = INPANALOG(m_FC);
114      nl_double  v_rng = INPANALOG(m_RNG);
115
116      /* coefficients */
117      const nl_double k1 = 1.9904769024796283E+03;
118      const nl_double k2 = 1.2070059213983407E+03;
119      const nl_double k3 = 1.3266985579561108E+03;
120      const nl_double k4 = -1.5500979825922698E+02;
121      const nl_double k5 = 2.8184536266938172E+00;
122      const nl_double k6 = -2.3503421582744556E+02;
123      const nl_double k7 = -3.3836786704527788E+02;
124      const nl_double k8 = -1.3569136703258670E+02;
125      const nl_double k9 = 2.9914575453819188E+00;
126      const nl_double k10 = 1.6855569086173170E+00;
127
128      /* scale due to input resistance */
129
130      /* Polyfunctional3D_model created by zunzun.com using sum of squared absolute error */
131
132      v_freq_2 = v_freq * v_freq;
133      v_freq_3 = v_freq_2 * v_freq;
134      v_freq_4 = v_freq_3 * v_freq;
135      freq = k1;
136      freq += k2 * v_freq;
137      freq += k3 * v_freq_2;
138      freq += k4 * v_freq_3;
139      freq += k5 * v_freq_4;
140      freq += k6 * v_rng;
141      freq += k7 * v_rng * v_freq;
142      freq += k8 * v_rng * v_freq_2;
143      freq += k9 * v_rng * v_freq_3;
144      freq += k10 * v_rng * v_freq_4;
145
146      freq *= NL_FCONST(0.1e-6) / m_CAP;
147
148      // FIXME: we need a possibility to remove entries from queue ...
149      //        or an exact model ...
150      m_clock.m_inc = netlist_time::from_double(0.5 / (double) freq);
151      //m_clock.update();
152
153      //NL_VERBOSE_OUT(("{1} {2} {3} {4}\n", name(), v_freq, v_rng, freq));
154   }
155
156   if (!m_clock.m_enableq && INPLOGIC(m_ENQ))
157   {
158      m_clock.m_enableq = 1;
159      m_clock.m_out = m_clock.m_out ^ 1;
160      OUTLOGIC(m_clock.m_Y, m_clock.m_out, netlist_time::from_nsec(1));
161   }
162   else if (m_clock.m_enableq && !INPLOGIC(m_ENQ))
163   {
164      m_clock.m_enableq = 0;
165      m_clock.m_out = m_clock.m_out ^ 1;
166      OUTLOGIC(m_clock.m_Y, m_clock.m_out, netlist_time::from_nsec(1));
167   }
168}
169
170NETLIB_UPDATE_PARAM(SN74LS629)
171{
172   update_dev();
173}
174
175
176
177NETLIB_START(SN74LS629_dip)
178{
179   register_sub("1", m_1);
180   register_sub("2", m_2);
181
182   register_subalias("1",  m_2.m_FC);
183   register_subalias("2",  m_1.m_FC);
184   register_subalias("3",  m_1.m_RNG);
185
186   register_subalias("6",  m_1.m_ENQ);
187   register_subalias("7",  m_1.m_clock.m_Y);
188
189   register_subalias("8",  m_1.m_R_FC.m_N);
190   register_subalias("9",  m_1.m_R_FC.m_N);
191   connect_late(m_1.m_R_FC.m_N, m_2.m_R_FC.m_N);
192
193   register_subalias("10",  m_2.m_clock.m_Y);
194
195   register_subalias("11",  m_2.m_ENQ);
196   register_subalias("14",  m_2.m_RNG);
197
198}
199
200NETLIB_UPDATE(SN74LS629_dip)
201{
202}
203
204NETLIB_RESET(SN74LS629_dip)
205{
206   m_1.do_reset();
207   m_2.do_reset();
208}
209
210NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_74ls629.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_74LS629.h
5 *
6 *  SN74LS629: VOLTAGE-CONTROLLED OSCILLATORS
7 *
8 *          +--------------+
9 *      2FC |1     ++    16| VCC
10 *      1FC |2           15| QSC VCC
11 *     1RNG |3           14| 2RNG
12 *     1CX1 |4  74LS629  13| 2CX1
13 *     1CX2 |5           12| 2CX2
14 *     1ENQ |6           11| 2ENQ
15 *       1Y |7           10| 2Y
16 *  OSC GND |8            9| GND
17 *          +--------------+
18 *
19 *  Naming conventions follow Texas Instruments datasheet
20 *
21 *  NOTE: The CX1 and CX2 pins are not connected!
22 *        The capacitor value has to be specified as a parameter.
23 *        There are more comments on the challenges of emulating this
24 *        chip in the *.c file
25 *
26 */
27
28#ifndef NLD_74LS629_H_
29#define NLD_74LS629_H_
30
31#include "nl_base.h"
32#include "analog/nld_twoterm.h"
33
34#define SN74LS629(_name, _cap)                                                      \
35      NET_REGISTER_DEV(SN74LS629, _name)                                          \
36      NETDEV_PARAMI(_name, CAP, _cap)
37
38NETLIB_NAMESPACE_DEVICES_START()
39
40NETLIB_SUBDEVICE(SN74LS629clk,
41   logic_input_t m_FB;
42   logic_output_t m_Y;
43
44   netlist_time m_inc;
45   netlist_sig_t m_enableq;
46   netlist_sig_t m_out;
47);
48
49NETLIB_DEVICE_WITH_PARAMS(SN74LS629,
50public:
51   NETLIB_NAME(SN74LS629clk) m_clock;
52   NETLIB_NAME(R_base) m_R_FC;
53   NETLIB_NAME(R_base) m_R_RNG;
54
55   logic_input_t m_ENQ;
56   analog_input_t m_RNG;
57   analog_input_t m_FC;
58
59   param_double_t m_CAP;
60);
61
62#define SN74LS629_DIP(_name, _cap1, _cap2)                                        \
63      NET_REGISTER_DEV(SN74LS629_DIP, _name)                                    \
64      NETDEV_PARAMI(_name, 1.CAP, _cap1)                                        \
65      NETDEV_PARAMI(_name, 2.CAP, _cap2)
66
67NETLIB_DEVICE(SN74LS629_dip,
68   NETLIB_NAME(SN74LS629) m_1;
69   NETLIB_NAME(SN74LS629) m_2;
70);
71
72NETLIB_NAMESPACE_DEVICES_END()
73
74
75#endif /* NLD_74LS629_H_ */
trunk/src/lib/netlist/devices/nld_82S16.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_82S16.c
5 *
6 */
7
8#include "nld_82S16.h"
9
10NETLIB_NAMESPACE_DEVICES_START()
11
12// FIXME: timing!
13// FIXME: optimize device (separate address decoder!)
14NETLIB_UPDATE(82S16)
15{
16   if (INPLOGIC(m_CE1Q) || INPLOGIC(m_CE2Q) || INPLOGIC(m_CE3Q))
17   {
18      // FIXME: Outputs are tristate. This needs to be properly implemented
19      OUTLOGIC(m_DOUTQ, 1, NLTIME_FROM_NS(20));
20      //for (int i=0; i<8; i++)
21         //m_A[i].inactivate();
22   }
23   else
24   {
25      int adr = 0;
26      for (int i=0; i<8; i++)
27      {
28         //m_A[i].activate();
29         adr |= (INPLOGIC(m_A[i]) << i);
30      }
31
32      if (!INPLOGIC(m_WEQ))
33      {
34         m_ram[adr] = INPLOGIC(m_DIN);
35      }
36      OUTLOGIC(m_DOUTQ, m_ram[adr] ^ 1, NLTIME_FROM_NS(20));
37   }
38}
39
40NETLIB_START(82S16)
41{
42   register_input("A0",    m_A[0]);
43   register_input("A1",    m_A[1]);
44   register_input("A2",    m_A[2]);
45   register_input("A3",    m_A[3]);
46   register_input("A4",    m_A[4]);
47   register_input("A5",    m_A[5]);
48   register_input("A6",    m_A[6]);
49   register_input("A7",    m_A[7]);
50
51   register_input("CE1Q",  m_CE1Q);
52   register_input("CE2Q",  m_CE2Q);
53   register_input("CE3Q",  m_CE3Q);
54
55   register_input("WEQ",   m_WEQ);
56   register_input("DIN",   m_DIN);
57
58   register_output("DOUTQ",m_DOUTQ);
59
60   save(NLNAME(m_ram));
61}
62
63NETLIB_RESET(82S16)
64{
65   for (int i=0; i<256; i++)
66   {
67      m_ram[i] = 0;
68   }
69}
70
71NETLIB_START(82S16_dip)
72{
73   register_input("2",     m_A[0]);
74   register_input("1",     m_A[1]);
75   register_input("15",    m_A[2]);
76   register_input("14",    m_A[3]);
77   register_input("7",     m_A[4]);
78   register_input("9",     m_A[5]);
79   register_input("10",    m_A[6]);
80   register_input("11",    m_A[7]);
81
82   register_input("3",     m_CE1Q);
83   register_input("4",     m_CE2Q);
84   register_input("5",     m_CE3Q);
85
86   register_input("12",    m_WEQ);
87   register_input("13",    m_DIN);
88
89   register_output("6",    m_DOUTQ);
90
91   save(NLNAME(m_ram));
92}
93
94NETLIB_RESET(82S16_dip)
95{
96   NETLIB_NAME(82S16)::reset();
97}
98
99NETLIB_UPDATE(82S16_dip)
100{
101   NETLIB_NAME(82S16)::update();
102}
103
104NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_82S16.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_82S16.h
5 *
6 *  DM82S16: 256 Bit bipolar ram
7 *
8 *          +--------------+
9 *       A1 |1     ++    16| VCC
10 *       A0 |2           15| A2
11 *     CE1Q |3           14| A3
12 *     CE2Q |4   82S16   13| DIN
13 *     CE3Q |5           12| WEQ
14 *    DOUTQ |6           11| A7
15 *       A4 |7           10| A6
16 *      GND |8            9| A5
17 *          +--------------+
18 *
19 *
20 *  Naming conventions follow Signetics datasheet
21 *
22 */
23
24#ifndef NLD_82S16_H_
25#define NLD_82S16_H_
26
27#include "nl_base.h"
28
29#define TTL_82S16(_name)                                     \
30      NET_REGISTER_DEV(TTL_82S16, _name)
31#define TTL_82S16_DIP(_name)                                 \
32      NET_REGISTER_DEV(TTL_82S16_DIP, _name)
33
34NETLIB_NAMESPACE_DEVICES_START()
35
36NETLIB_DEVICE(82S16,
37
38   logic_input_t m_A[8];
39   logic_input_t m_CE1Q;
40   logic_input_t m_CE2Q;
41   logic_input_t m_CE3Q;
42   logic_input_t m_WEQ;
43   logic_input_t m_DIN;
44   logic_output_t m_DOUTQ;
45
46   //netlist_state_t<UINT8[256]> m_ram;
47   UINT8 m_ram[256];
48);
49
50NETLIB_DEVICE_DERIVED_PURE(82S16_dip, 82S16);
51
52NETLIB_NAMESPACE_DEVICES_END()
53
54#endif /* NLD_82S16_H_ */
trunk/src/lib/netlist/devices/nld_9310.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_9310.c
5 *
6 */
7
8#include "nld_9310.h"
9
10#define MAXCNT 9
11
12NETLIB_NAMESPACE_DEVICES_START()
13
14NETLIB_START(9310)
15{
16   register_sub("subABCD", subABCD);
17   sub.m_ABCD = &subABCD;
18   register_sub("sub", sub);
19
20   register_subalias("CLK", sub.m_CLK);
21
22   register_input("ENP", m_ENP);
23   register_input("ENT", m_ENT);
24   register_input("CLRQ", m_CLRQ);
25   register_input("LOADQ", m_LOADQ);
26
27   register_subalias("A", subABCD.m_A);
28   register_subalias("B", subABCD.m_B);
29   register_subalias("C", subABCD.m_C);
30   register_subalias("D", subABCD.m_D);
31
32   register_subalias("QA", sub.m_QA);
33   register_subalias("QB", sub.m_QB);
34   register_subalias("QC", sub.m_QC);
35   register_subalias("QD", sub.m_QD);
36   register_subalias("RC", sub.m_RC);
37
38}
39
40NETLIB_RESET(9310)
41{
42   sub.do_reset();
43   subABCD.do_reset();
44}
45
46NETLIB_START(9310_subABCD)
47{
48   register_input("A", m_A);
49   register_input("B", m_B);
50   register_input("C", m_C);
51   register_input("D", m_D);
52
53}
54
55NETLIB_RESET(9310_subABCD)
56{
57#if 0
58   m_A.inactivate();
59   m_B.inactivate();
60   m_C.inactivate();
61   m_D.inactivate();
62#endif
63}
64
65NETLIB_UPDATE(9310_subABCD)
66{
67}
68
69NETLIB_START(9310_sub)
70{
71   register_input("CLK", m_CLK);
72
73   register_output("QA", m_QA);
74   register_output("QB", m_QB);
75   register_output("QC", m_QC);
76   register_output("QD", m_QD);
77   register_output("RC", m_RC);
78
79   save(NLNAME(m_cnt));
80   save(NLNAME(m_loadq));
81   save(NLNAME(m_ent));
82}
83
84NETLIB_RESET(9310_sub)
85{
86   m_CLK.set_state(logic_t::STATE_INP_LH);
87   m_cnt = 0;
88   m_loadq = 1;
89   m_ent = 1;
90}
91
92NETLIB_UPDATE(9310_sub)
93{
94   if (m_loadq)
95   {
96#if 0
97      m_cnt = (m_cnt < MAXCNT) ? m_cnt + 1 : 0;
98      update_outputs(m_cnt);
99      OUTLOGIC(m_RC, m_ent & (m_cnt == MAXCNT), NLTIME_FROM_NS(20));
100#else
101      switch (m_cnt)
102      {
103         case MAXCNT - 1:
104            m_cnt = MAXCNT;
105            OUTLOGIC(m_RC, m_ent, NLTIME_FROM_NS(20));
106            OUTLOGIC(m_QA, 1, NLTIME_FROM_NS(20));
107            break;
108         case MAXCNT:
109            OUTLOGIC(m_RC, 0, NLTIME_FROM_NS(20));
110            m_cnt = 0;
111            update_outputs_all(m_cnt, NLTIME_FROM_NS(20));
112            break;
113         default:
114            m_cnt++;
115            update_outputs(m_cnt);
116      }
117#endif
118   }
119   else
120   {
121      m_cnt = m_ABCD->read_ABCD();
122      update_outputs_all(m_cnt, NLTIME_FROM_NS(22));
123      OUTLOGIC(m_RC, m_ent & (m_cnt == MAXCNT), NLTIME_FROM_NS(27));
124   }
125}
126
127NETLIB_UPDATE(9310)
128{
129   sub.m_loadq = INPLOGIC(m_LOADQ);
130   sub.m_ent = INPLOGIC(m_ENT);
131   const netlist_sig_t clrq = INPLOGIC(m_CLRQ);
132
133   if ((!sub.m_loadq || (sub.m_ent & INPLOGIC(m_ENP))) && clrq)
134   {
135      sub.m_CLK.activate_lh();
136      OUTLOGIC(sub.m_RC, sub.m_ent & (sub.m_cnt == MAXCNT), NLTIME_FROM_NS(27));
137   }
138   else
139   {
140      sub.m_CLK.inactivate();
141      if (!clrq && (sub.m_cnt>0))
142      {
143         sub.update_outputs_all(0, NLTIME_FROM_NS(36));
144         sub.m_cnt = 0;
145         //return;
146      }
147      OUTLOGIC(sub.m_RC, sub.m_ent & (sub.m_cnt == MAXCNT), NLTIME_FROM_NS(27));
148   }
149}
150
151inline NETLIB_FUNC_VOID(9310_sub, update_outputs_all, (const UINT8 cnt, const netlist_time out_delay))
152{
153   OUTLOGIC(m_QA, (cnt >> 0) & 1, out_delay);
154   OUTLOGIC(m_QB, (cnt >> 1) & 1, out_delay);
155   OUTLOGIC(m_QC, (cnt >> 2) & 1, out_delay);
156   OUTLOGIC(m_QD, (cnt >> 3) & 1, out_delay);
157}
158
159inline NETLIB_FUNC_VOID(9310_sub, update_outputs, (const UINT8 cnt))
160{
161   /* static */ const netlist_time out_delay = NLTIME_FROM_NS(20);
162#if 0
163//    for (int i=0; i<4; i++)
164//        OUTLOGIC(m_Q[i], (cnt >> i) & 1, delay[i]);
165   OUTLOGIC(m_QA, (cnt >> 0) & 1, out_delay);
166   OUTLOGIC(m_QB, (cnt >> 1) & 1, out_delay);
167   OUTLOGIC(m_QC, (cnt >> 2) & 1, out_delay);
168   OUTLOGIC(m_QD, (cnt >> 3) & 1, out_delay);
169#else
170   if ((cnt & 1) == 1)
171      OUTLOGIC(m_QA, 1, out_delay);
172   else
173   {
174      OUTLOGIC(m_QA, 0, out_delay);
175      switch (cnt)
176      {
177      case 0x00:
178         OUTLOGIC(m_QB, 0, out_delay);
179         OUTLOGIC(m_QC, 0, out_delay);
180         OUTLOGIC(m_QD, 0, out_delay);
181         break;
182      case 0x02:
183      case 0x06:
184      case 0x0A:
185      case 0x0E:
186         OUTLOGIC(m_QB, 1, out_delay);
187         break;
188      case 0x04:
189      case 0x0C:
190         OUTLOGIC(m_QB, 0, out_delay);
191         OUTLOGIC(m_QC, 1, out_delay);
192         break;
193      case 0x08:
194         OUTLOGIC(m_QB, 0, out_delay);
195         OUTLOGIC(m_QC, 0, out_delay);
196         OUTLOGIC(m_QD, 1, out_delay);
197         break;
198      }
199
200   }
201#endif
202}
203
204NETLIB_START(9310_dip)
205{
206   NETLIB_NAME(9310)::start();
207
208   register_subalias("1", m_CLRQ);
209   register_subalias("2", sub.m_CLK);
210   register_subalias("3", subABCD.m_A);
211   register_subalias("4", subABCD.m_B);
212   register_subalias("5", subABCD.m_C);
213   register_subalias("6", subABCD.m_D);
214   register_subalias("7", m_ENP);
215   // register_subalias("8", ); --> GND
216
217   register_subalias("9", m_LOADQ);
218   register_subalias("10", m_ENT);
219   register_subalias("11", sub.m_QD);
220   register_subalias("12", sub.m_QC);
221   register_subalias("13", sub.m_QB);
222   register_subalias("14", sub.m_QA);
223   register_subalias("15", sub.m_RC);
224   // register_subalias("16", ); --> VCC
225}
226
227NETLIB_UPDATE(9310_dip)
228{
229   NETLIB_NAME(9310)::update();
230}
231
232NETLIB_RESET(9310_dip)
233{
234   NETLIB_NAME(9310)::reset();
235}
236
237NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_9310.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_9310.h
5 *
6 *  DM9310: Synchronous 4-Bit Counters
7 *
8 *  FIXME: This should be merged with the 9316. The only difference is MAXCNT!
9 *
10 *          +--------------+
11 *    CLEAR |1     ++    16| VCC
12 *    CLOCK |2           15| RC (Ripple Carry)
13 *        A |3           14| QA
14 *        B |4    9310   13| QB
15 *        C |5           12| QC
16 *        D |6           11| QD
17 * Enable P |7           10| Enable T
18 *      GND |8            9| LOAD
19 *          +--------------+
20 *
21 *          Counter Sequence
22 *
23 *          +-------++----+----+----+----+----+
24 *          | COUNT || QD | QC | QB | QA | RC |
25 *          +=======++====+====+====+====+====+
26 *          |    0  ||  0 |  0 |  0 |  0 |  0 |
27 *          |    1  ||  0 |  0 |  0 |  1 |  0 |
28 *          |    2  ||  0 |  0 |  1 |  0 |  0 |
29 *          |    3  ||  0 |  0 |  1 |  1 |  0 |
30 *          |    4  ||  0 |  1 |  0 |  0 |  0 |
31 *          |    5  ||  0 |  1 |  0 |  1 |  0 |
32 *          |    6  ||  0 |  1 |  1 |  0 |  0 |
33 *          |    7  ||  0 |  1 |  1 |  1 |  0 |
34 *          |    8  ||  1 |  0 |  0 |  0 |  0 |
35 *          |    9  ||  1 |  0 |  0 |  1 |  0 |
36 *          +-------++----+----+----+----+----+
37 *
38 *          Reset count function: Please refer to
39 *          National Semiconductor datasheet (timing diagramm)
40 *
41 *  Naming conventions follow National Semiconductor datasheet
42 *
43 */
44
45#ifndef NLD_9310_H_
46#define NLD_9310_H_
47
48#include "nl_base.h"
49
50#define TTL_9310(_name, _CLK, _ENP, _ENT, _CLRQ, _LOADQ, _A, _B, _C, _D)            \
51      NET_REGISTER_DEV(TTL_9310, _name)                                               \
52      NET_CONNECT(_name, CLK, _CLK)                                               \
53      NET_CONNECT(_name, ENP,  _ENP)                                              \
54      NET_CONNECT(_name, ENT,  _ENT)                                              \
55      NET_CONNECT(_name, CLRQ, _CLRQ)                                             \
56      NET_CONNECT(_name, LOADQ,_LOADQ)                                            \
57      NET_CONNECT(_name, A,    _A)                                                \
58      NET_CONNECT(_name, B,    _B)                                                \
59      NET_CONNECT(_name, C,    _C)                                                \
60      NET_CONNECT(_name, D,    _D)
61
62#define TTL_9310_DIP(_name)                                                         \
63      NET_REGISTER_DEV(TTL_9310_DIP, _name)
64
65NETLIB_NAMESPACE_DEVICES_START()
66
67NETLIB_SUBDEVICE(9310_subABCD,
68   logic_input_t m_A;
69   logic_input_t m_B;
70   logic_input_t m_C;
71   logic_input_t m_D;
72
73   ATTR_HOT inline UINT8 read_ABCD() const
74   {
75      //return (INPLOGIC_PASSIVE(m_D) << 3) | (INPLOGIC_PASSIVE(m_C) << 2) | (INPLOGIC_PASSIVE(m_B) << 1) | (INPLOGIC_PASSIVE(m_A) << 0);
76      return (INPLOGIC(m_D) << 3) | (INPLOGIC(m_C) << 2) | (INPLOGIC(m_B) << 1) | (INPLOGIC(m_A) << 0);
77   }
78);
79
80NETLIB_SUBDEVICE(9310_sub,
81   ATTR_HOT inline void update_outputs_all(const UINT8 cnt, const netlist_time out_delay);
82   ATTR_HOT inline void update_outputs(const UINT8 cnt);
83
84   logic_input_t m_CLK;
85
86   UINT8 m_cnt;
87   NETLIB_NAME(9310_subABCD) *m_ABCD;
88   netlist_sig_t m_loadq;
89   netlist_sig_t m_ent;
90
91   logic_output_t m_QA;
92   logic_output_t m_QB;
93   logic_output_t m_QC;
94   logic_output_t m_QD;
95   logic_output_t m_RC;
96);
97
98NETLIB_DEVICE(9310,
99   NETLIB_NAME(9310_sub) sub;
100   NETLIB_NAME(9310_subABCD) subABCD;
101   logic_input_t m_ENP;
102   logic_input_t m_ENT;
103   logic_input_t m_CLRQ;
104   logic_input_t m_LOADQ;
105);
106
107NETLIB_DEVICE_DERIVED_PURE(9310_dip, 9310);
108
109NETLIB_NAMESPACE_DEVICES_END()
110
111#endif /* NLD_9310_H_ */
trunk/src/lib/netlist/devices/nld_9312.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_9312.c
5 *
6 */
7
8/*
9 *          +---+---+---+---++---+---+
10 *          | C | B | A | G || Y | YQ|
11 *          +===+===+===+===++===+===+
12 *          | X | X | X | 1 ||  0| 1 |
13 *          | 0 | 0 | 0 | 0 || D0|D0Q|
14 *          | 0 | 0 | 1 | 0 || D1|D1Q|
15 *          | 0 | 1 | 0 | 0 || D2|D2Q|
16 *          | 0 | 1 | 1 | 0 || D3|D3Q|
17 *          | 1 | 0 | 0 | 0 || D4|D4Q|
18 *          | 1 | 0 | 1 | 0 || D5|D5Q|
19 *          | 1 | 1 | 0 | 0 || D6|D6Q|
20 *          | 1 | 1 | 1 | 0 || D7|D7Q|
21 *          +---+---+---+---++---+---+
22*/
23#include "nld_9312.h"
24
25NETLIB_NAMESPACE_DEVICES_START()
26
27#if (1 && USE_TRUTHTABLE)
28nld_9312::truthtable_t nld_9312::m_ttbl;
29
30/* FIXME: Data changes are propagating faster than changing selects A,B,C
31 *        Please refer to data sheet.
32 *        This would require a state machine, thus we do not
33 *        do this right now.
34 */
35
36const char *nld_9312::m_desc[] = {
37      " C, B, A, G,D0,D1,D2,D3,D4,D5,D6,D7| Y,YQ",
38      " X, X, X, 1, X, X, X, X, X, X, X, X| 0, 1|33,19",
39      " 0, 0, 0, 0, 0, X, X, X, X, X, X, X| 0, 1|33,28",
40      " 0, 0, 0, 0, 1, X, X, X, X, X, X, X| 1, 0|33,28",
41      " 0, 0, 1, 0, X, 0, X, X, X, X, X, X| 0, 1|33,28",
42      " 0, 0, 1, 0, X, 1, X, X, X, X, X, X| 1, 0|33,28",
43      " 0, 1, 0, 0, X, X, 0, X, X, X, X, X| 0, 1|33,28",
44      " 0, 1, 0, 0, X, X, 1, X, X, X, X, X| 1, 0|33,28",
45      " 0, 1, 1, 0, X, X, X, 0, X, X, X, X| 0, 1|33,28",
46      " 0, 1, 1, 0, X, X, X, 1, X, X, X, X| 1, 0|33,28",
47      " 1, 0, 0, 0, X, X, X, X, 0, X, X, X| 0, 1|33,28",
48      " 1, 0, 0, 0, X, X, X, X, 1, X, X, X| 1, 0|33,28",
49      " 1, 0, 1, 0, X, X, X, X, X, 0, X, X| 0, 1|33,28",
50      " 1, 0, 1, 0, X, X, X, X, X, 1, X, X| 1, 0|33,28",
51      " 1, 1, 0, 0, X, X, X, X, X, X, 0, X| 0, 1|33,28",
52      " 1, 1, 0, 0, X, X, X, X, X, X, 1, X| 1, 0|33,28",
53      " 1, 1, 1, 0, X, X, X, X, X, X, X, 0| 0, 1|33,28",
54      " 1, 1, 1, 0, X, X, X, X, X, X, X, 1| 1, 0|33,28",
55      ""
56};
57#else
58
59NETLIB_UPDATE(9312)
60{
61   const UINT8 G = INPLOGIC(m_G);
62   if (G)
63   {
64      /* static */ const netlist_time delay[2] = { NLTIME_FROM_NS(33), NLTIME_FROM_NS(19) };
65      OUTLOGIC(m_Y, 0, delay[0]);
66      OUTLOGIC(m_YQ, 1, delay[1]);
67
68      m_A.inactivate();
69      m_B.inactivate();
70      m_C.inactivate();
71      m_last_G = G;
72   }
73   else
74   {
75      if (m_last_G)
76      {
77         m_last_G = G;
78         m_A.activate();
79         m_B.activate();
80         m_C.activate();
81      }
82      /* static */ const netlist_time delay[2] = { NLTIME_FROM_NS(33), NLTIME_FROM_NS(28) };
83      const UINT8 chan = INPLOGIC(m_A) | (INPLOGIC(m_B)<<1) | (INPLOGIC(m_C)<<2);
84      if (m_last_chan != chan)
85      {
86         m_D[m_last_chan].inactivate();
87         m_D[chan].activate();
88      }
89      const UINT8 val = INPLOGIC(m_D[chan]);
90      OUTLOGIC(m_Y, val, delay[val]);
91      OUTLOGIC(m_YQ, !val, delay[!val]);
92      m_last_chan = chan;
93   }
94}
95
96NETLIB_START(9312)
97{
98   register_input("G",         m_G);
99   register_input("A",         m_A);
100   register_input("B",         m_B);
101   register_input("C",         m_C);
102
103   register_input("D0",        m_D[0]);
104   register_input("D1",        m_D[1]);
105   register_input("D2",        m_D[2]);
106   register_input("D3",        m_D[3]);
107   register_input("D4",        m_D[4]);
108   register_input("D5",        m_D[5]);
109   register_input("D6",        m_D[6]);
110   register_input("D7",        m_D[7]);
111
112   register_output("Y",        m_Y);
113   register_output("YQ",       m_YQ);
114
115   m_last_chan = 0;
116   m_last_G = 0;
117
118   save(NLNAME(m_last_chan));
119   save(NLNAME(m_last_G));
120}
121
122NETLIB_RESET(9312)
123{
124}
125#endif
126
127NETLIB_START(9312_dip)
128{
129   register_sub("1", m_sub);
130
131#if (1 && USE_TRUTHTABLE)
132
133   register_subalias("13", m_sub.m_I[0]);
134   register_subalias("12", m_sub.m_I[1]);
135   register_subalias("11", m_sub.m_I[2]);
136   register_subalias("10", m_sub.m_I[3]);
137
138   register_subalias("1", m_sub.m_I[4]);
139   register_subalias("2", m_sub.m_I[5]);
140   register_subalias("3", m_sub.m_I[6]);
141   register_subalias("4", m_sub.m_I[7]);
142   register_subalias("5", m_sub.m_I[8]);
143   register_subalias("6", m_sub.m_I[9]);
144   register_subalias("7", m_sub.m_I[10]);
145   register_subalias("9", m_sub.m_I[11]);
146
147   register_subalias("15", m_sub.m_Q[0]); // Y
148   register_subalias("14", m_sub.m_Q[1]); // YQ
149
150#else
151
152   register_subalias("13", m_sub.m_C);
153   register_subalias("12", m_sub.m_B);
154   register_subalias("11", m_sub.m_A);
155   register_subalias("10", m_sub.m_G);
156
157   register_subalias("1", m_sub.m_D[0]);
158   register_subalias("2", m_sub.m_D[1]);
159   register_subalias("3", m_sub.m_D[2]);
160   register_subalias("4", m_sub.m_D[3]);
161   register_subalias("5", m_sub.m_D[4]);
162   register_subalias("6", m_sub.m_D[5]);
163   register_subalias("7", m_sub.m_D[6]);
164   register_subalias("9", m_sub.m_D[7]);
165
166   register_subalias("15", m_sub.m_Y); // Y
167   register_subalias("14", m_sub.m_YQ); // YQ
168
169#endif
170}
171
172NETLIB_UPDATE(9312_dip)
173{
174   /* only called during startup */
175   m_sub.update_dev();
176}
177
178NETLIB_RESET(9312_dip)
179{
180   m_sub.do_reset();
181}
182NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_9312.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_9312.h
5 *
6 *  DM9312: One of Eight Line Data Selectors/Multiplexers
7 *
8 *          +--------------+
9 *       D0 |1     ++    16| VCC
10 *       D1 |2           15| Y
11 *       D2 |3           14| YQ
12 *       D3 |4    9312   13| C
13 *       D4 |5           12| B
14 *       D5 |6           11| A
15 *       D6 |7           10| G   Strobe
16 *      GND |8            9| D7
17 *          +--------------+
18 *                  __
19 *          +---+---+---+---++---+---+
20 *          | C | B | A | G || Y | YQ|
21 *          +===+===+===+===++===+===+
22 *          | X | X | X | 1 ||  0| 1 |
23 *          | 0 | 0 | 0 | 0 || D0|D0Q|
24 *          | 0 | 0 | 1 | 0 || D1|D1Q|
25 *          | 0 | 1 | 0 | 0 || D2|D2Q|
26 *          | 0 | 1 | 1 | 0 || D3|D3Q|
27 *          | 1 | 0 | 0 | 0 || D4|D4Q|
28 *          | 1 | 0 | 1 | 0 || D5|D5Q|
29 *          | 1 | 1 | 0 | 0 || D6|D6Q|
30 *          | 1 | 1 | 1 | 0 || D7|D7Q|
31 *          +---+---+---+---++---+---+
32 *
33 *  Naming conventions follow National Semiconductor datasheet
34 *
35 */
36
37#ifndef NLD_9312_H_
38#define NLD_9312_H_
39
40#include "nld_signal.h"
41#include "nld_truthtable.h"
42
43#define TTL_9312(_name)                                                \
44      NET_REGISTER_DEV(TTL_9312, _name)
45
46#define TTL_9312_DIP(_name)                                            \
47      NET_REGISTER_DEV(TTL_9312_DIP, _name)
48
49NETLIB_NAMESPACE_DEVICES_START()
50
51#if (USE_TRUTHTABLE)
52/* The truthtable implementation is a lot faster than
53 * the carefully crafted code :-(
54 */
55NETLIB_TRUTHTABLE(9312, 12, 2, 0);
56#else
57
58NETLIB_DEVICE(9312,
59public:
60//      C, B, A, G,D0,D1,D2,D3,D4,D5,D6,D7| Y,YQ
61   netlist_logic_input_t m_A;
62   netlist_logic_input_t m_B;
63   netlist_logic_input_t m_C;
64   netlist_logic_input_t m_G;
65   netlist_logic_input_t m_D[8];
66   netlist_logic_output_t m_Y;
67   netlist_logic_output_t m_YQ;
68
69   UINT8 m_last_chan;
70   UINT8 m_last_G;
71);
72
73#endif
74
75NETLIB_DEVICE(9312_dip,
76   NETLIB_NAME(9312) m_sub;
77);
78
79NETLIB_NAMESPACE_DEVICES_END()
80
81#endif /* NLD_9312_H_ */
trunk/src/lib/netlist/devices/nld_9316.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_9316.c
5 *
6 */
7
8#include "nld_9316.h"
9
10#define MAXCNT 15
11
12NETLIB_NAMESPACE_DEVICES_START()
13
14NETLIB_START(9316)
15{
16   register_sub("subABCD", subABCD);
17   sub.m_ABCD = &subABCD;
18   register_sub("sub", sub);
19
20   register_subalias("CLK", sub.m_CLK);
21
22   register_input("ENP", m_ENP);
23   register_input("ENT", m_ENT);
24   register_input("CLRQ", m_CLRQ);
25   register_input("LOADQ", m_LOADQ);
26
27   register_subalias("A", subABCD.m_A);
28   register_subalias("B", subABCD.m_B);
29   register_subalias("C", subABCD.m_C);
30   register_subalias("D", subABCD.m_D);
31
32   register_subalias("QA", sub.m_QA);
33   register_subalias("QB", sub.m_QB);
34   register_subalias("QC", sub.m_QC);
35   register_subalias("QD", sub.m_QD);
36   register_subalias("RC", sub.m_RC);
37
38}
39
40NETLIB_RESET(9316)
41{
42   sub.do_reset();
43   subABCD.do_reset();
44}
45
46NETLIB_START(9316_subABCD)
47{
48   register_input("A", m_A);
49   register_input("B", m_B);
50   register_input("C", m_C);
51   register_input("D", m_D);
52
53}
54
55NETLIB_RESET(9316_subABCD)
56{
57#if 0
58   m_A.inactivate();
59   m_B.inactivate();
60   m_C.inactivate();
61   m_D.inactivate();
62#endif
63}
64
65NETLIB_UPDATE(9316_subABCD)
66{
67}
68
69NETLIB_START(9316_sub)
70{
71   register_input("CLK", m_CLK);
72
73   register_output("QA", m_QA);
74   register_output("QB", m_QB);
75   register_output("QC", m_QC);
76   register_output("QD", m_QD);
77   register_output("RC", m_RC);
78
79   save(NLNAME(m_cnt));
80   save(NLNAME(m_loadq));
81   save(NLNAME(m_ent));
82}
83
84NETLIB_RESET(9316_sub)
85{
86   m_CLK.set_state(logic_t::STATE_INP_LH);
87   m_cnt = 0;
88   m_loadq = 1;
89   m_ent = 1;
90}
91
92NETLIB_UPDATE(9316_sub)
93{
94   if (m_loadq)
95   {
96      switch (m_cnt)
97      {
98         case MAXCNT - 1:
99            m_cnt = MAXCNT;
100            OUTLOGIC(m_RC, m_ent, NLTIME_FROM_NS(27));
101            OUTLOGIC(m_QA, 1, NLTIME_FROM_NS(20));
102            break;
103         case MAXCNT:
104            OUTLOGIC(m_RC, 0, NLTIME_FROM_NS(27));
105            m_cnt = 0;
106            update_outputs_all(m_cnt, NLTIME_FROM_NS(20));
107            break;
108         default:
109            m_cnt++;
110            update_outputs(m_cnt);
111            break;
112      }
113   }
114   else
115   {
116      m_cnt = m_ABCD->read_ABCD();
117      OUTLOGIC(m_RC, m_ent & (m_cnt == MAXCNT), NLTIME_FROM_NS(27));
118      update_outputs_all(m_cnt, NLTIME_FROM_NS(22));
119   }
120}
121
122NETLIB_UPDATE(9316)
123{
124   sub.m_loadq = INPLOGIC(m_LOADQ);
125   sub.m_ent = INPLOGIC(m_ENT);
126   const netlist_sig_t clrq = INPLOGIC(m_CLRQ);
127
128   if (((sub.m_loadq ^ 1) | (sub.m_ent & INPLOGIC(m_ENP))) & clrq)
129   {
130      sub.m_CLK.activate_lh();
131      OUTLOGIC(sub.m_RC, sub.m_ent & (sub.m_cnt == MAXCNT), NLTIME_FROM_NS(27));
132   }
133   else
134   {
135      sub.m_CLK.inactivate();
136      if (!clrq && (sub.m_cnt>0))
137      {
138         sub.update_outputs_all(0, NLTIME_FROM_NS(36));
139         sub.m_cnt = 0;
140         //return;
141      }
142      OUTLOGIC(sub.m_RC, sub.m_ent & (sub.m_cnt == MAXCNT), NLTIME_FROM_NS(27));
143   }
144}
145
146inline NETLIB_FUNC_VOID(9316_sub, update_outputs_all, (const UINT8 cnt, const netlist_time out_delay))
147{
148   OUTLOGIC(m_QA, (cnt >> 0) & 1, out_delay);
149   OUTLOGIC(m_QB, (cnt >> 1) & 1, out_delay);
150   OUTLOGIC(m_QC, (cnt >> 2) & 1, out_delay);
151   OUTLOGIC(m_QD, (cnt >> 3) & 1, out_delay);
152}
153
154inline NETLIB_FUNC_VOID(9316_sub, update_outputs, (const UINT8 cnt))
155{
156   /* static */ const netlist_time out_delay = NLTIME_FROM_NS(20);
157#if 0
158//    for (int i=0; i<4; i++)
159//        OUTLOGIC(m_Q[i], (cnt >> i) & 1, delay[i]);
160   OUTLOGIC(m_QA, (cnt >> 0) & 1, out_delay);
161   OUTLOGIC(m_QB, (cnt >> 1) & 1, out_delay);
162   OUTLOGIC(m_QC, (cnt >> 2) & 1, out_delay);
163   OUTLOGIC(m_QD, (cnt >> 3) & 1, out_delay);
164#else
165   if ((cnt & 1) == 1)
166      OUTLOGIC(m_QA, 1, out_delay);
167   else
168   {
169      OUTLOGIC(m_QA, 0, out_delay);
170      switch (cnt)
171      {
172      case 0x00:
173         OUTLOGIC(m_QB, 0, out_delay);
174         OUTLOGIC(m_QC, 0, out_delay);
175         OUTLOGIC(m_QD, 0, out_delay);
176         break;
177      case 0x02:
178      case 0x06:
179      case 0x0A:
180      case 0x0E:
181         OUTLOGIC(m_QB, 1, out_delay);
182         break;
183      case 0x04:
184      case 0x0C:
185         OUTLOGIC(m_QB, 0, out_delay);
186         OUTLOGIC(m_QC, 1, out_delay);
187         break;
188      case 0x08:
189         OUTLOGIC(m_QB, 0, out_delay);
190         OUTLOGIC(m_QC, 0, out_delay);
191         OUTLOGIC(m_QD, 1, out_delay);
192         break;
193      }
194
195   }
196#endif
197}
198
199NETLIB_START(9316_dip)
200{
201   NETLIB_NAME(9316)::start();
202
203   register_subalias("1", m_CLRQ);
204   register_subalias("2", sub.m_CLK);
205   register_subalias("3", subABCD.m_A);
206   register_subalias("4", subABCD.m_B);
207   register_subalias("5", subABCD.m_C);
208   register_subalias("6", subABCD.m_D);
209   register_subalias("7", m_ENP);
210   // register_subalias("8", ); --> GND
211
212   register_subalias("9", m_LOADQ);
213   register_subalias("10", m_ENT);
214   register_subalias("11", sub.m_QD);
215   register_subalias("12", sub.m_QC);
216   register_subalias("13", sub.m_QB);
217   register_subalias("14", sub.m_QA);
218   register_subalias("15", sub.m_RC);
219   // register_subalias("16", ); --> VCC
220}
221
222NETLIB_UPDATE(9316_dip)
223{
224   NETLIB_NAME(9316)::update();
225}
226
227NETLIB_RESET(9316_dip)
228{
229   NETLIB_NAME(9316)::reset();
230}
231
232NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_9316.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_9316.h
5 *
6 *  DM9316: Synchronous 4-Bit Counters
7 *
8 *          +--------------+
9 *    CLEAR |1     ++    16| VCC
10 *    CLOCK |2           15| RC (Ripple Carry)
11 *        A |3           14| QA
12 *        B |4    9316   13| QB
13 *        C |5           12| QC
14 *        D |6           11| QD
15 * Enable P |7           10| Enable T
16 *      GND |8            9| LOAD
17 *          +--------------+
18 *
19 *          Counter Sequence
20 *
21 *          +-------++----+----+----+----+----+
22 *          | COUNT || QD | QC | QB | QA | RC |
23 *          +=======++====+====+====+====+====+
24 *          |    0  ||  0 |  0 |  0 |  0 |  0 |
25 *          |    1  ||  0 |  0 |  0 |  1 |  0 |
26 *          |    2  ||  0 |  0 |  1 |  0 |  0 |
27 *          |    3  ||  0 |  0 |  1 |  1 |  0 |
28 *          |    4  ||  0 |  1 |  0 |  0 |  0 |
29 *          |    5  ||  0 |  1 |  0 |  1 |  0 |
30 *          |    6  ||  0 |  1 |  1 |  0 |  0 |
31 *          |    7  ||  0 |  1 |  1 |  1 |  0 |
32 *          |    8  ||  1 |  0 |  0 |  0 |  0 |
33 *          |    9  ||  1 |  0 |  0 |  1 |  0 |
34 *          |   10  ||  1 |  0 |  1 |  0 |  0 |
35 *          |   11  ||  1 |  0 |  1 |  1 |  0 |
36 *          |   12  ||  1 |  1 |  0 |  0 |  0 |
37 *          |   13  ||  1 |  1 |  0 |  1 |  0 |
38 *          |   14  ||  1 |  1 |  1 |  0 |  0 |
39 *          |   15  ||  1 |  1 |  1 |  1 |  1 |
40 *          +-------++----+----+----+----+----+
41 *
42 *          Reset count function: Please refer to
43 *          National Semiconductor datasheet (timing diagramm)
44 *
45 *  Naming conventions follow National Semiconductor datasheet
46 *
47 */
48
49#ifndef NLD_9316_H_
50#define NLD_9316_H_
51
52#include "nl_base.h"
53
54#define TTL_9316(_name, _CLK, _ENP, _ENT, _CLRQ, _LOADQ, _A, _B, _C, _D)            \
55      NET_REGISTER_DEV(TTL_9316, _name)                                               \
56      NET_CONNECT(_name, CLK, _CLK)                                               \
57      NET_CONNECT(_name, ENP,  _ENP)                                              \
58      NET_CONNECT(_name, ENT,  _ENT)                                              \
59      NET_CONNECT(_name, CLRQ, _CLRQ)                                             \
60      NET_CONNECT(_name, LOADQ,_LOADQ)                                            \
61      NET_CONNECT(_name, A,    _A)                                                \
62      NET_CONNECT(_name, B,    _B)                                                \
63      NET_CONNECT(_name, C,    _C)                                                \
64      NET_CONNECT(_name, D,    _D)
65
66#define TTL_9316_DIP(_name)                                                         \
67      NET_REGISTER_DEV(TTL_9316_DIP, _name)
68
69NETLIB_NAMESPACE_DEVICES_START()
70
71NETLIB_SUBDEVICE(9316_subABCD,
72   logic_input_t m_A;
73   logic_input_t m_B;
74   logic_input_t m_C;
75   logic_input_t m_D;
76
77   ATTR_HOT inline UINT8 read_ABCD() const
78   {
79      //return (INPLOGIC_PASSIVE(m_D) << 3) | (INPLOGIC_PASSIVE(m_C) << 2) | (INPLOGIC_PASSIVE(m_B) << 1) | (INPLOGIC_PASSIVE(m_A) << 0);
80      return (INPLOGIC(m_D) << 3) | (INPLOGIC(m_C) << 2) | (INPLOGIC(m_B) << 1) | (INPLOGIC(m_A) << 0);
81   }
82);
83
84NETLIB_SUBDEVICE(9316_sub,
85   ATTR_HOT inline void update_outputs_all(const UINT8 cnt, const netlist_time out_delay);
86   ATTR_HOT inline void update_outputs(const UINT8 cnt);
87
88   logic_input_t m_CLK;
89
90   logic_output_t m_QA;
91   logic_output_t m_QB;
92   logic_output_t m_QC;
93   logic_output_t m_QD;
94   logic_output_t m_RC;
95
96   UINT8 m_cnt;
97   NETLIB_NAME(9316_subABCD) *m_ABCD;
98   netlist_sig_t m_loadq;
99   netlist_sig_t m_ent;
100
101);
102
103NETLIB_DEVICE(9316,
104   NETLIB_NAME(9316_sub) sub;
105   NETLIB_NAME(9316_subABCD) subABCD;
106   logic_input_t m_ENP;
107   logic_input_t m_ENT;
108   logic_input_t m_CLRQ;
109   logic_input_t m_LOADQ;
110);
111
112NETLIB_DEVICE_DERIVED_PURE(9316_dip, 9316);
113
114NETLIB_NAMESPACE_DEVICES_END()
115
116#endif /* NLD_9316_H_ */
trunk/src/lib/netlist/devices/nld_cmos.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_cmos.h
5 *
6 */
7
8#ifndef NLD_CMOS_H_
9#define NLD_CMOS_H_
10
11#include "nl_base.h"
12#include "analog/nld_twoterm.h"
13
14NETLIB_NAMESPACE_DEVICES_START()
15
16class nld_vdd_vss : public device_t
17{
18   public:
19      nld_vdd_vss ()
20      : device_t()
21         { }
22
23      analog_input_t m_vdd;
24      analog_input_t m_vss;
25
26   protected:
27      ATTR_HOT void update() {};
28      ATTR_HOT void start()
29      {
30         register_input("VDD", m_vdd);
31         register_input("VSS", m_vss);
32      };
33      ATTR_HOT void reset()  {};
34
35public:
36   ATTR_HOT inline nl_double vdd() { return INPANALOG(m_vdd); }
37   ATTR_HOT inline nl_double vss() { return INPANALOG(m_vss); }
38};
39
40NETLIB_NAMESPACE_DEVICES_END()
41
42#endif /* NLD_CMOS_H_ */
trunk/src/lib/netlist/devices/nld_legacy.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_legacy.c
5 *
6 */
7
8#include "nld_legacy.h"
9#include "nl_setup.h"
10
11NETLIB_NAMESPACE_DEVICES_START()
12
13NETLIB_START(nicRSFF)
14{
15   register_input("S", m_S);
16   register_input("R", m_R);
17   register_output("Q", m_Q);
18   register_output("QQ", m_QQ);
19}
20
21NETLIB_RESET(nicRSFF)
22{
23   m_Q.initial(0);
24   m_QQ.initial(1);
25}
26
27NETLIB_UPDATE(nicRSFF)
28{
29   if (!INPLOGIC(m_S))
30   {
31      OUTLOGIC(m_Q,  1, NLTIME_FROM_NS(20));
32      OUTLOGIC(m_QQ, 0, NLTIME_FROM_NS(20));
33   }
34   else if (!INPLOGIC(m_R))
35   {
36      OUTLOGIC(m_Q,  0, NLTIME_FROM_NS(20));
37      OUTLOGIC(m_QQ, 1, NLTIME_FROM_NS(20));
38   }
39}
40
41NETLIB_START(nicDelay)
42{
43   register_input("1", m_I);
44   register_output("2", m_Q);
45
46   register_param("L_TO_H", m_L_to_H, 10);
47   register_param("H_TO_L", m_H_to_L, 10);
48
49   save(NLNAME(m_last));
50
51}
52
53NETLIB_RESET(nicDelay)
54{
55   m_Q.initial(0);
56}
57
58NETLIB_UPDATE_PARAM(nicDelay)
59{
60}
61
62NETLIB_UPDATE(nicDelay)
63{
64   netlist_sig_t nval = INPLOGIC(m_I);
65   if (nval && !m_last)
66   {
67      // L_to_H
68      OUTLOGIC(m_Q,  1, NLTIME_FROM_NS(m_L_to_H.Value()));
69   }
70   else if (!nval && m_last)
71   {
72      // H_to_L
73      OUTLOGIC(m_Q,  0, NLTIME_FROM_NS(m_H_to_L.Value()));
74   }
75   m_last = nval;
76}
77
78NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_legacy.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_legacy.h
5 *
6 * All of the devices below needs to disappear at some time .....
7 *
8 *
9 */
10
11#pragma once
12
13#ifndef NLD_LEGACY_H_
14#define NLD_LEGACY_H_
15
16#include "nl_base.h"
17
18NETLIB_NAMESPACE_DEVICES_START()
19
20// ----------------------------------------------------------------------------------------
21// Macros
22// ----------------------------------------------------------------------------------------
23
24#define NETDEV_RSFF(_name)                                                          \
25      NET_REGISTER_DEV(NETDEV_RSFF, _name)
26
27#define NETDEV_DELAY(_name)                                                         \
28      NET_REGISTER_DEV(NETDEV_DELAY, _name)
29
30// ----------------------------------------------------------------------------------------
31// Devices ...
32// ----------------------------------------------------------------------------------------
33
34NETLIB_DEVICE(nicRSFF,
35   logic_input_t m_S;
36   logic_input_t m_R;
37
38   logic_output_t m_Q;
39   logic_output_t m_QQ;
40);
41
42
43NETLIB_DEVICE_WITH_PARAMS(nicDelay,
44   logic_input_t m_I;
45
46   logic_output_t m_Q;
47
48   param_int_t m_L_to_H;
49   param_int_t m_H_to_L;
50
51   UINT8 m_last;
52);
53
54NETLIB_NAMESPACE_DEVICES_END()
55
56#endif /* NLD_LEGACY_H_ */
trunk/src/lib/netlist/devices/nld_log.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_log.c
5 *
6 */
7
8#include "nld_log.h"
9//#include "sound/wavwrite.h"
10
11NETLIB_NAMESPACE_DEVICES_START()
12
13//FIXME: what to do with save states?
14
15NETLIB_START(log)
16{
17   register_input("I", m_I);
18
19   pstring filename = pfmt("{1}.log")(name());
20   m_strm = palloc(pofilestream(filename));
21}
22
23NETLIB_RESET(log)
24{
25}
26
27NETLIB_UPDATE(log)
28{
29   /* use pstring::sprintf, it is a LOT faster */
30   m_strm->writeline(pfmt("{1} {2}").e(netlist().time().as_double(),".9").e((nl_double) INPANALOG(m_I)));
31}
32
33NETLIB_NAME(log)::~NETLIB_NAME(log)()
34{
35   m_strm->close();
36   pfree(m_strm);
37}
38
39NETLIB_START(logD)
40{
41   NETLIB_NAME(log)::start();
42   register_input("I2", m_I2);
43}
44
45NETLIB_RESET(logD)
46{
47}
48
49NETLIB_UPDATE(logD)
50{
51   m_strm->writeline(pfmt("{1} {2}").e(netlist().time().as_double(),".9").e((nl_double) (INPANALOG(m_I) - INPANALOG(m_I2))));
52}
53
54// FIXME: Implement wav later, this must be clock triggered device where the input to be written
55//        is on a subdevice ..
56#if 0
57NETLIB_START(wav)
58{
59   register_input("I", m_I);
60
61   pstring filename = "netlist_" + name() + ".wav";
62   m_file = wav_open(filename, sample_rate(), active_inputs()/2)
63}
64
65NETLIB_UPDATE(wav)
66{
67   fprintf(m_file, "%e %e\n", netlist().time().as_double(), INPANALOG(m_I));
68}
69
70NETLIB_NAME(log)::~NETLIB_NAME(wav)()
71{
72   fclose(m_file);
73}
74#endif
75
76NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_log.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_log.h
5 *
6 *  Devices supporting analysis and logging
7 *
8 *  nld_log:
9 *
10 *          +---------+
11 *          |    ++   |
12 *        I |         | ==> Log to file "netlist_" + name() + ".log"
13 *          |         |
14 *          +---------+
15 *
16 */
17
18#ifndef NLD_LOG_H_
19#define NLD_LOG_H_
20
21#include "nl_base.h"
22#include "plib/pstream.h"
23
24#define LOG(_name, _I)                                                        \
25      NET_REGISTER_DEV(??PG, _name)                                         \
26      NET_CONNECT(_name, I, _I)
27
28NETLIB_NAMESPACE_DEVICES_START()
29
30NETLIB_DEVICE(log,
31   ~NETLIB_NAME(log)();
32   analog_input_t m_I;
33protected:
34   pofilestream *m_strm;
35);
36
37#define LOGD(_name, _I, _I2)                                                 \
38      NET_REGISTER_DEV(LOGD, _name)                                        \
39      NET_CONNECT(_name, I, _I)                                            \
40      NET_CONNECT(_name, I2, _I2)
41
42NETLIB_DEVICE_DERIVED(logD, log,
43   analog_input_t m_I2;
44);
45
46#if 0
47NETLIB_DEVICE(wav,
48   ~NETLIB_NAME(wav)();
49   analog_input_t m_I;
50private:
51   // FIXME: rewrite sound/wavwrite.h to be an object ...
52   void *m_file;
53);
54#endif
55
56NETLIB_NAMESPACE_DEVICES_END()
57
58#endif /* NLD_LOG_H_ */
trunk/src/lib/netlist/devices/nld_mm5837.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_MM5837.c
5 *
6 */
7
8#include <solver/nld_solver.h>
9#include "nld_mm5837.h"
10#include "nl_setup.h"
11
12#define R_LOW (1000)
13#define R_HIGH (1000)
14
15NETLIB_NAMESPACE_DEVICES_START()
16
17NETLIB_START(MM5837_dip)
18{
19   /* clock */
20   register_output("Q", m_Q);
21   register_input("FB", m_feedback);
22   m_inc = netlist_time::from_hz(56000);
23   connect_late(m_feedback, m_Q);
24
25   /* output */
26   register_sub("RV", m_RV);
27   register_terminal("_RV1", m_RV.m_P);
28   register_terminal("_RV2", m_RV.m_N);
29   register_output("_Q", m_V0);
30   connect_late(m_RV.m_N, m_V0);
31
32   /* device */
33   register_input("1", m_VDD);
34   register_input("2", m_VGG);
35   register_subalias("3", m_RV.m_P);
36   register_input("4", m_VSS);
37
38   save(NLNAME(m_shift));
39}
40
41NETLIB_RESET(MM5837_dip)
42{
43   m_V0.initial(0.0);
44   m_RV.do_reset();
45   m_RV.set(NL_FCONST(1.0) / R_LOW, 0.0, 0.0);
46
47   m_shift = 0x1ffff;
48   m_is_timestep = m_RV.m_P.net().as_analog().solver()->is_timestep();
49}
50
51NETLIB_UPDATE(MM5837_dip)
52{
53   OUTLOGIC(m_Q, !m_Q.net().as_logic().new_Q(), m_inc  );
54
55   /* shift register
56    *
57    * 17 bits, bits 17 & 14 feed back to input
58    *
59    */
60
61   const UINT32 last_state = m_shift & 0x01;
62   /* shift */
63   m_shift = (m_shift >> 1) | (((m_shift & 0x01) ^ ((m_shift >> 3) & 0x01)) << 16);
64   const UINT32 state = m_shift & 0x01;
65
66   if (state != last_state)
67   {
68      const nl_double R = state ? R_HIGH : R_LOW;
69      const nl_double V = state ? INPANALOG(m_VDD) : INPANALOG(m_VSS);
70
71      // We only need to update the net first if this is a time stepping net
72      if (m_is_timestep)
73         m_RV.update_dev();
74      m_RV.set(NL_FCONST(1.0) / R, V, 0.0);
75      m_RV.m_P.schedule_after(NLTIME_FROM_NS(1));
76   }
77
78}
79
80
81
82NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_mm5837.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_MM5837.h
5 *
6 *  MM5837: Digital noise source
7 *
8 *          +--------+
9 *      VDD |1  ++  8| NC
10 *      VGG |2      7| NC
11 *      OUT |3      6| NC
12 *      VSS |4      5| NC
13 *          +--------+
14 *
15 *  Naming conventions follow National Semiconductor datasheet
16 *
17 */
18
19#ifndef NLD_MM5837_H_
20#define NLD_MM5837_H_
21
22#include "nl_base.h"
23#include "analog/nld_twoterm.h"
24
25#define MM5837_DIP(_name)                                                        \
26      NET_REGISTER_DEV(MM5837_DIP, _name)
27
28NETLIB_NAMESPACE_DEVICES_START()
29
30NETLIB_DEVICE(MM5837_dip,
31
32   analog_input_t m_VDD;
33   analog_input_t m_VGG;
34   analog_input_t m_VSS;
35
36   /* output stage */
37   nld_twoterm m_RV;
38   analog_output_t m_V0; /* could be gnd as well */
39
40   /* clock stage */
41   logic_input_t m_feedback;
42   logic_output_t m_Q;
43   netlist_time m_inc;
44
45   /* state */
46   UINT32 m_shift;
47
48   /* cache */
49   bool m_is_timestep;
50);
51
52NETLIB_NAMESPACE_DEVICES_END()
53
54#endif /* NLD_MM5837_H_ */
trunk/src/lib/netlist/devices/nld_ne555.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_NE555.c
5 *
6 */
7
8#include <solver/nld_solver.h>
9#include "nld_ne555.h"
10#include "nl_setup.h"
11
12#define R_OFF (1E20)
13#define R_ON (25)   // Datasheet states a maximum discharge of 200mA, R = 5V / 0.2
14
15NETLIB_NAMESPACE_DEVICES_START()
16
17inline nl_double NETLIB_NAME(NE555)::clamp(const nl_double v, const nl_double a, const nl_double b)
18{
19   nl_double ret = v;
20   nl_double vcc = TERMANALOG(m_R1.m_P);
21
22   if (ret >  vcc - a)
23      ret = vcc - a;
24   if (ret < b)
25      ret = b;
26   return ret;
27}
28
29NETLIB_START(NE555)
30{
31   register_sub("R1", m_R1);
32   register_sub("R2", m_R2);
33   register_sub("R3", m_R3);
34   register_sub("RDIS", m_RDIS);
35
36   register_subalias("GND",  m_R3.m_N);    // Pin 1
37   register_input("TRIG",    m_TRIG);      // Pin 2
38   register_output("OUT",    m_OUT);       // Pin 3
39   register_input("RESET",   m_RESET);     // Pin 4
40   register_subalias("CONT", m_R1.m_N);    // Pin 5
41   register_input("THRESH",  m_THRES);     // Pin 6
42   register_subalias("DISCH", m_RDIS.m_P); // Pin 7
43   register_subalias("VCC",  m_R1.m_P);    // Pin 8
44
45   connect_late(m_R1.m_N, m_R2.m_P);
46   connect_late(m_R2.m_N, m_R3.m_P);
47   connect_late(m_RDIS.m_N, m_R3.m_N);
48
49   save(NLNAME(m_last_out));
50   save(NLNAME(m_ff));
51}
52
53NETLIB_RESET(NE555)
54{
55   m_R1.do_reset();
56   m_R2.do_reset();
57   m_R3.do_reset();
58   m_RDIS.do_reset();
59
60   m_R1.set_R(5000);
61   m_R2.set_R(5000);
62   m_R3.set_R(5000);
63   m_RDIS.set_R(R_OFF);
64
65   m_last_out = true;
66}
67
68NETLIB_UPDATE(NE555)
69{
70   // FIXME: assumes GND is connected to 0V.
71
72   nl_double vt = clamp(TERMANALOG(m_R2.m_P), 0.7, 1.4);
73   bool bthresh = (INPANALOG(m_THRES) > vt);
74   bool btrig = (INPANALOG(m_TRIG) > clamp(TERMANALOG(m_R2.m_N), 0.7, 1.4));
75
76   if (!btrig)
77   {
78      m_ff = true;
79   }
80   else if (bthresh)
81   {
82      m_ff = false;
83   }
84
85   bool out = (!INPLOGIC(m_RESET) ? false : m_ff);
86
87   if (m_last_out && !out)
88   {
89      m_RDIS.update_dev();
90      OUTANALOG(m_OUT, TERMANALOG(m_R3.m_N));
91      m_RDIS.set_R(R_ON);
92   }
93   else if (!m_last_out && out)
94   {
95      m_RDIS.update_dev();
96      // FIXME: Should be delayed by 100ns
97      OUTANALOG(m_OUT, TERMANALOG(m_R1.m_P));
98      m_RDIS.set_R(R_OFF);
99   }
100   m_last_out = out;
101}
102
103
104NETLIB_START(NE555_dip)
105{
106   NETLIB_NAME(NE555)::start();
107
108   register_subalias("1",  m_R3.m_N);      // Pin 1
109   register_subalias("2",    m_TRIG);      // Pin 2
110   register_subalias("3",    m_OUT);       // Pin 3
111   register_subalias("4",   m_RESET);      // Pin 4
112   register_subalias("5", m_R1.m_N);       // Pin 5
113   register_subalias("6",  m_THRES);       // Pin 6
114   register_subalias("7", m_RDIS.m_P);     // Pin 7
115   register_subalias("8",  m_R1.m_P);      // Pin 8
116
117}
118
119NETLIB_UPDATE(NE555_dip)
120{
121   NETLIB_NAME(NE555)::update();
122}
123
124NETLIB_RESET(NE555_dip)
125{
126   NETLIB_NAME(NE555)::reset();
127}
128
129NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_ne555.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_NE555.h
5 *
6 *  NE555: PRECISION TIMERS
7 *
8 *          +--------+
9 *      GND |1  ++  8| VCC
10 *     TRIG |2      7| DISCH
11 *      OUT |3      6| THRES
12 *    RESET |4      5| CONT
13 *          +--------+
14 *
15 *  Naming conventions follow Texas Instruments datasheet
16 *
17 */
18
19#ifndef NLD_NE555_H_
20#define NLD_NE555_H_
21
22#include "nl_base.h"
23#include "analog/nld_twoterm.h"
24
25#define NE555(_name)                                                        \
26      NET_REGISTER_DEV(NE555, _name)
27
28NETLIB_NAMESPACE_DEVICES_START()
29
30NETLIB_DEVICE(NE555,
31   NETLIB_NAME(R) m_R1;
32   NETLIB_NAME(R) m_R2;
33   NETLIB_NAME(R) m_R3;
34   NETLIB_NAME(R) m_RDIS;
35
36   logic_input_t m_RESET;
37   analog_input_t m_THRES;
38   analog_input_t m_TRIG;
39   analog_output_t m_OUT;
40
41   bool m_last_out;
42   bool m_ff;
43
44   inline nl_double clamp(const nl_double v, const nl_double a, const nl_double b);
45
46);
47
48#define NE555_DIP(_name)                                                         \
49      NET_REGISTER_DEV(NE555_DIP, _name)
50
51NETLIB_DEVICE_DERIVED_PURE(NE555_dip, NE555);
52
53NETLIB_NAMESPACE_DEVICES_END()
54
55#endif /* NLD_NE555_H_ */
trunk/src/lib/netlist/devices/nld_r2r_dac.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_R2R_dac.c
5 *
6 */
7
8#include "nld_r2r_dac.h"
9
10NETLIB_NAMESPACE_DEVICES_START()
11
12NETLIB_START(r2r_dac)
13{
14   NETLIB_NAME(twoterm)::start();
15   register_terminal("VOUT", m_P);
16   register_terminal("VGND", m_N);
17   register_param("R", m_R, 1.0);
18   register_param("VIN", m_VIN, 1.0);
19   register_param("N", m_num, 1);
20   register_param("VAL", m_val, 1);
21}
22
23NETLIB_RESET(r2r_dac)
24{
25   NETLIB_NAME(twoterm)::reset();
26}
27
28NETLIB_UPDATE(r2r_dac)
29{
30   NETLIB_NAME(twoterm)::update();
31}
32
33NETLIB_UPDATE_PARAM(r2r_dac)
34{
35   update_dev();
36
37   nl_double V = m_VIN.Value() / (nl_double) (1 << m_num.Value()) * (nl_double) m_val.Value();
38
39   this->set(1.0 / m_R.Value(), V, 0.0);
40}
41
42NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_r2r_dac.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_R2R_DAC.h
5 *
6 *  DMR2R_DAC: R-2R DAC
7 *
8 *  Generic R-2R DAC ... This is fast.
9 *                 2R
10 *  Bit n    >----RRR----+---------> Vout
11 *                       |
12 *                       R
13 *                       R R
14 *                       R
15 *                       |
16 *                       .
17 *                       .
18 *                 2R    |
19 *  Bit 2    >----RRR----+
20 *                       |
21 *                       R
22 *                       R R
23 *                       R
24 *                       |
25 *                 2R    |
26 *  Bit 1    >----RRR----+
27 *                       |
28 *                       R
29 *                       R 2R
30 *                       R
31 *                       |
32 *                      V0
33 *
34 * Using Thevenin's Theorem, this can be written as
35 *
36 *          +---RRR-----------> Vout
37 *          |
38 *          V
39 *          V  V = VAL / 2^n * Vin
40 *          V
41 *          |
42 *          V0
43 *
44 */
45
46#ifndef NLD_R2R_DAC_H_
47#define NLD_R2R_DAC_H_
48
49#include "nl_base.h"
50#include "analog/nld_twoterm.h"
51
52#define R2R_DAC(_name, _VIN, _R, _N)                                            \
53      NET_REGISTER_DEV(R2R_DAC, _name)                                       \
54      NETDEV_PARAMI(_name, VIN, _VIN)                                        \
55      NETDEV_PARAMI(_name, R,   _R)                                          \
56      NETDEV_PARAMI(_name, N,   _N)
57
58NETLIB_NAMESPACE_DEVICES_START()
59
60NETLIB_DEVICE_WITH_PARAMS_DERIVED(r2r_dac, twoterm,
61   param_double_t m_VIN;
62   param_double_t m_R;
63   param_int_t m_num;
64   param_int_t m_val;
65);
66
67NETLIB_NAMESPACE_DEVICES_END()
68
69
70#endif /* NLD_R2R_DAC_H_ */
trunk/src/lib/netlist/devices/nld_signal.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_signal.h
5 *
6 */
7
8#ifndef NLD_SIGNAL_H_
9#define NLD_SIGNAL_H_
10
11#include "nl_base.h"
12
13// ----------------------------------------------------------------------------------------
14// MACROS
15// ----------------------------------------------------------------------------------------
16
17#define NETLIB_SIGNAL(_name, _num_input, _check, _invert)                           \
18   class NETLIB_NAME(_name) : public net_signal_t<_num_input, _check, _invert>     \
19   {                                                                               \
20   public:                                                                         \
21      NETLIB_NAME(_name) ()                                             \
22      : net_signal_t<_num_input, _check, _invert>() { }                           \
23   }
24
25NETLIB_NAMESPACE_DEVICES_START()
26
27// ----------------------------------------------------------------------------------------
28// net_signal_t
29// ----------------------------------------------------------------------------------------
30
31template <int _numdev, int _check, int _invert>
32class net_signal_t : public device_t
33{
34public:
35   net_signal_t()
36   : device_t(), m_active(1)
37   {
38   }
39
40   void start()
41   {
42      const char *sIN[8] = { "A", "B", "C", "D", "E", "F", "G", "H" };
43
44      register_output("Q", m_Q[0]);
45      for (int i=0; i < _numdev; i++)
46      {
47         register_input(sIN[i], m_I[i]);
48      }
49      save(NLNAME(m_active));
50   }
51
52   void reset()
53   {
54      m_Q[0].initial(0);
55      m_active = 1;
56   }
57
58   ATTR_HOT inline netlist_sig_t process()
59   {
60      for (int i = 0; i< _numdev; i++)
61      {
62         this->m_I[i].activate();
63         if (INPLOGIC(this->m_I[i]) == _check)
64         {
65            for (int j = 0; j < i; j++)
66               this->m_I[j].inactivate();
67            for (int j = i + 1; j < _numdev; j++)
68               this->m_I[j].inactivate();
69            return _check ^ (1 ^ _invert);
70         }
71      }
72      return _check ^ _invert;
73   }
74
75   ATTR_HOT virtual void inc_active()
76   {
77      const netlist_time times[2] = { NLTIME_FROM_NS(15), NLTIME_FROM_NS(22)};
78      nl_assert(netlist().use_deactivate());
79      if (++m_active == 1)
80      {
81         // FIXME: need to activate before time is accessed !
82         netlist_time mt = netlist_time::zero;
83         for (int i = 0; i< _numdev; i++)
84         {
85            if (this->m_I[i].net().time() > mt)
86               mt = this->m_I[i].net().time();
87         }
88         netlist_sig_t r = process();
89         m_Q[0].net().set_Q_time(r, mt + times[r]);
90      }
91   }
92
93   ATTR_HOT virtual void dec_active()
94   {
95      nl_assert(netlist().use_deactivate());
96      if (--m_active == 0)
97      {
98         for (int i = 0; i< _numdev; i++)
99            m_I[i].inactivate();
100      }
101   }
102
103   virtual void update()
104   {
105      const netlist_time times[2] = { NLTIME_FROM_NS(15), NLTIME_FROM_NS(22)};
106
107      netlist_sig_t r = process();
108      OUTLOGIC(this->m_Q[0], r, times[r]);
109   }
110
111public:
112   logic_input_t m_I[_numdev];
113   logic_output_t m_Q[1];
114   INT32 m_active;
115};
116
117NETLIB_NAMESPACE_DEVICES_END()
118
119#endif /* NLD_SIGNAL_H_ */
trunk/src/lib/netlist/devices/nld_system.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_system.c
5 *
6 */
7
8#include <solver/nld_solver.h>
9#include "nld_system.h"
10
11NETLIB_NAMESPACE_DEVICES_START()
12
13// ----------------------------------------------------------------------------------------
14// netlistparams
15// ----------------------------------------------------------------------------------------
16
17NETLIB_START(netlistparams)
18{
19   register_param("USE_DEACTIVATE", m_use_deactivate, 0);
20}
21
22NETLIB_RESET(netlistparams)
23{
24}
25
26NETLIB_UPDATE_PARAM(netlistparams)
27{
28}
29
30NETLIB_UPDATE(netlistparams)
31{
32}
33
34
35// ----------------------------------------------------------------------------------------
36// clock
37// ----------------------------------------------------------------------------------------
38
39NETLIB_START(clock)
40{
41   register_output("Q", m_Q);
42   register_input("FB", m_feedback);
43
44   register_param("FREQ", m_freq, 7159000.0 * 5.0);
45   m_inc = netlist_time::from_hz(m_freq.Value()*2);
46
47   connect_late(m_feedback, m_Q);
48}
49
50NETLIB_RESET(clock)
51{
52}
53
54NETLIB_UPDATE_PARAM(clock)
55{
56   m_inc = netlist_time::from_hz(m_freq.Value()*2);
57}
58
59NETLIB_UPDATE(clock)
60{
61   OUTLOGIC(m_Q, !m_Q.net().as_logic().new_Q(), m_inc  );
62}
63
64// ----------------------------------------------------------------------------------------
65// extclock
66// ----------------------------------------------------------------------------------------
67
68NETLIB_START(extclock)
69{
70   register_output("Q", m_Q);
71   register_input("FB", m_feedback);
72
73   register_param("FREQ", m_freq, 7159000.0 * 5.0);
74   register_param("PATTERN", m_pattern, "1,1");
75   register_param("OFFSET", m_offset, 0.0);
76   m_inc[0] = netlist_time::from_hz(m_freq.Value()*2);
77
78   connect_late(m_feedback, m_Q);
79   {
80      netlist_time base = netlist_time::from_hz(m_freq.Value()*2);
81      pstring_list_t pat(m_pattern.Value(),",");
82      m_off = netlist_time::from_double(m_offset.Value());
83
84      int pati[256];
85      m_size = pat.size();
86      int total = 0;
87      for (int i=0; i<m_size; i++)
88      {
89         pati[i] = pat[i].as_long();
90         total += pati[i];
91      }
92      netlist_time ttotal = netlist_time::zero;
93      for (int i=0; i<m_size - 1; i++)
94      {
95         m_inc[i] = base * pati[i];
96         ttotal += m_inc[i];
97      }
98      m_inc[m_size - 1] = base * total - ttotal;
99   }
100   save(NLNAME(m_cnt));
101   save(NLNAME(m_off));
102}
103
104NETLIB_RESET(extclock)
105{
106   m_cnt = 0;
107   m_off = netlist_time::from_double(m_offset.Value());
108   m_Q.initial(0);
109}
110
111NETLIB_UPDATE_PARAM(extclock)
112{
113}
114
115NETLIB_UPDATE(extclock)
116{
117   if (m_cnt != 0)
118   {
119      OUTLOGIC(m_Q, (m_cnt & 1) ^ 1, m_inc[m_cnt]);
120      m_cnt = (m_cnt + 1) % m_size;
121   }
122   else
123   {
124      OUTLOGIC(m_Q, (m_cnt & 1) ^ 1, m_inc[0] + m_off);
125      m_cnt = 1;
126      m_off = netlist_time::zero;
127   }
128}
129
130// ----------------------------------------------------------------------------------------
131// logic_input
132// ----------------------------------------------------------------------------------------
133
134NETLIB_START(logic_input)
135{
136   /* make sure we get the family first */
137   register_param("FAMILY", m_FAMILY, "FAMILY(TYPE=TTL)");
138   set_logic_family(netlist().setup().family_from_model(m_FAMILY.Value()));
139
140   register_output("Q", m_Q);
141   register_param("IN", m_IN, 0);
142}
143
144NETLIB_RESET(logic_input)
145{
146}
147
148NETLIB_STOP(logic_input)
149{
150   if (m_logic_family != NULL)
151      if (!m_logic_family->m_is_static)
152         pfree(m_logic_family);
153}
154
155
156NETLIB_UPDATE(logic_input)
157{
158   OUTLOGIC(m_Q, m_IN.Value() & 1, netlist_time::from_nsec(1));
159}
160
161NETLIB_UPDATE_PARAM(logic_input)
162{
163   update();
164}
165
166// ----------------------------------------------------------------------------------------
167// analog_input
168// ----------------------------------------------------------------------------------------
169
170NETLIB_START(analog_input)
171{
172   register_output("Q", m_Q);
173   register_param("IN", m_IN, 0.0);
174}
175
176NETLIB_RESET(analog_input)
177{
178}
179
180NETLIB_UPDATE(analog_input)
181{
182   OUTANALOG(m_Q, m_IN.Value());
183}
184
185NETLIB_UPDATE_PARAM(analog_input)
186{
187   update();
188}
189
190// ----------------------------------------------------------------------------------------
191// nld_d_to_a_proxy
192// ----------------------------------------------------------------------------------------
193
194void nld_d_to_a_proxy::start()
195{
196   nld_base_d_to_a_proxy::start();
197
198   register_sub("RV", m_RV);
199   register_terminal("1", m_RV.m_P);
200   register_terminal("2", m_RV.m_N);
201
202   register_output("_Q", m_Q);
203   register_subalias("Q", m_RV.m_P);
204
205   connect_direct(m_RV.m_N, m_Q);
206
207   save(NLNAME(m_last_state));
208}
209
210void nld_d_to_a_proxy::reset()
211{
212   m_Q.initial(0.0);
213   m_last_state = -1;
214   m_RV.do_reset();
215   m_is_timestep = m_RV.m_P.net().as_analog().solver()->is_timestep();
216   m_RV.set(NL_FCONST(1.0) / logic_family().m_R_low, logic_family().m_low_V, 0.0);
217}
218
219ATTR_HOT void nld_d_to_a_proxy::update()
220{
221   const int state = INPLOGIC(m_I);
222   if (state != m_last_state)
223   {
224      m_last_state = state;
225      const nl_double R = state ? logic_family().m_R_high : logic_family().m_R_low;
226      const nl_double V = state ? logic_family().m_high_V : logic_family().m_low_V;
227
228      // We only need to update the net first if this is a time stepping net
229      if (m_is_timestep)
230      {
231         m_RV.update_dev();
232      }
233      m_RV.set(NL_FCONST(1.0) / R, V, 0.0);
234      m_RV.m_P.schedule_after(NLTIME_FROM_NS(1));
235   }
236}
237
238
239// -----------------------------------------------------------------------------
240// nld_res_sw
241// -----------------------------------------------------------------------------
242
243NETLIB_START(res_sw)
244{
245   register_sub("R", m_R);
246   register_input("I", m_I);
247   register_param("RON", m_RON, 1.0);
248   register_param("ROFF", m_ROFF, 1.0E20);
249
250   register_subalias("1", m_R.m_P);
251   register_subalias("2", m_R.m_N);
252
253   save(NLNAME(m_last_state));
254}
255
256NETLIB_RESET(res_sw)
257{
258   m_last_state = 0;
259   m_R.set_R(m_ROFF.Value());
260}
261
262NETLIB_UPDATE(res_sw)
263{
264   const int state = INPLOGIC(m_I);
265   if (state != m_last_state)
266   {
267      m_last_state = state;
268      const nl_double R = state ? m_RON.Value() : m_ROFF.Value();
269
270      // We only need to update the net first if this is a time stepping net
271      if (0) // m_R.m_P.net().as_analog().solver()->is_timestep())
272      {
273         m_R.update_dev();
274         m_R.set_R(R);
275         m_R.m_P.schedule_after(NLTIME_FROM_NS(1));
276      }
277      else
278      {
279         m_R.set_R(R);
280         m_R.m_P.schedule_after(NLTIME_FROM_NS(1));
281         //m_R.update_dev();
282      }
283   }
284}
285
286NETLIB_UPDATE_PARAM(res_sw)
287{
288   // nothing, not intended to be called
289}
290
291/* -----------------------------------------------------------------------------
292 * nld_function
293 * ----------------------------------------------------------------------------- */
294
295NETLIB_START(function)
296{
297   register_param("N", m_N, 2);
298   register_param("FUNC", m_func, "");
299   register_output("Q", m_Q);
300
301   for (int i=0; i < m_N; i++)
302      register_input(pfmt("A{1}")(i), m_I[i]);
303
304   pstring_list_t cmds(m_func.Value(), " ");
305   m_precompiled.clear();
306
307   for (std::size_t i=0; i < cmds.size(); i++)
308   {
309      pstring cmd = cmds[i];
310      rpn_inst rc;
311      if (cmd == "+")
312         rc.m_cmd = ADD;
313      else if (cmd == "-")
314         rc.m_cmd = SUB;
315      else if (cmd == "*")
316         rc.m_cmd = MULT;
317      else if (cmd == "/")
318         rc.m_cmd = DIV;
319      else if (cmd == "/")
320         rc.m_cmd = DIV;
321      else if (cmd.startsWith("A"))
322      {
323         rc.m_cmd = PUSH_INPUT;
324         rc.m_param = cmd.substr(1).as_long();
325      }
326      else
327      {
328         bool err = false;
329         rc.m_cmd = PUSH_CONST;
330         rc.m_param = cmd.as_double(&err);
331         if (err)
332            netlist().log().fatal("nld_function: unknown/misformatted token <{1}> in <{2}>", cmd, m_func.Value());
333      }
334      m_precompiled.add(rc);
335   }
336
337}
338
339NETLIB_RESET(function)
340{
341   m_Q.initial(0.0);
342}
343
344NETLIB_UPDATE(function)
345{
346   //nl_double val = INPANALOG(m_I[0]) * INPANALOG(m_I[1]) * 0.2;
347   //OUTANALOG(m_Q, val);
348   nl_double stack[20];
349   unsigned ptr = 0;
350   unsigned e = m_precompiled.size();
351   for (unsigned i = 0; i<e; i++)
352   {
353      rpn_inst &rc = m_precompiled[i];
354      switch (rc.m_cmd)
355      {
356         case ADD:
357            ptr--;
358            stack[ptr-1] = stack[ptr] + stack[ptr-1];
359            break;
360         case MULT:
361            ptr--;
362            stack[ptr-1] = stack[ptr] * stack[ptr-1];
363            break;
364         case SUB:
365            ptr--;
366            stack[ptr-1] = stack[ptr-1] - stack[ptr];
367            break;
368         case DIV:
369            ptr--;
370            stack[ptr-1] = stack[ptr-1] / stack[ptr];
371            break;
372         case PUSH_INPUT:
373            stack[ptr++] = INPANALOG(m_I[(int) rc.m_param]);
374            break;
375         case PUSH_CONST:
376            stack[ptr++] = rc.m_param;
377            break;
378      }
379   }
380   OUTANALOG(m_Q, stack[ptr-1]);
381}
382
383
384NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_system.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_system.h
5 *
6 * netlist devices defined in the core
7 */
8
9#ifndef NLD_SYSTEM_H_
10#define NLD_SYSTEM_H_
11
12#include "nl_setup.h"
13#include "nl_base.h"
14#include "nl_factory.h"
15#include "analog/nld_twoterm.h"
16
17// -----------------------------------------------------------------------------
18// Macros
19// -----------------------------------------------------------------------------
20
21#define TTL_INPUT(_name, _v)                                                   \
22      NET_REGISTER_DEV(TTL_INPUT, _name)                                   \
23      PARAM(_name.IN, _v)
24
25#define LOGIC_INPUT(_name, _v, _family)                                        \
26      NET_REGISTER_DEV(LOGIC_INPUT, _name)                                   \
27      PARAM(_name.IN, _v)                                                    \
28      PARAM(_name.FAMILY, _family)
29
30#define ANALOG_INPUT(_name, _v)                                                \
31      NET_REGISTER_DEV(ANALOG_INPUT, _name)                                  \
32      PARAM(_name.IN, _v)
33
34#define MAINCLOCK(_name, _freq)                                                \
35      NET_REGISTER_DEV(MAINCLOCK, _name)                                     \
36      PARAM(_name.FREQ, _freq)
37
38#define CLOCK(_name, _freq)                                                    \
39      NET_REGISTER_DEV(CLOCK, _name)                                         \
40      PARAM(_name.FREQ, _freq)
41
42#define EXTCLOCK(_name, _freq, _pattern)                                       \
43      NET_REGISTER_DEV(EXTCLOCK, _name)                                      \
44      PARAM(_name.FREQ, _freq)                                               \
45      PARAM(_name.PATTERN, _pattern)
46
47#define GNDA()                                                                 \
48      NET_REGISTER_DEV(GNDA, GND)
49
50#define DUMMY_INPUT(_name)                                                     \
51      NET_REGISTER_DEV(DUMMY_INPUT, _name)
52
53//FIXME: Usage discouraged, use OPTIMIZE_FRONTIER instead
54#define FRONTIER_DEV(_name, _IN, _G, _OUT)                                     \
55      NET_REGISTER_DEV(FRONTIER_DEV, _name)                                      \
56      NET_C(_IN, _name.I)                                                    \
57      NET_C(_G,  _name.G)                                                    \
58      NET_C(_OUT, _name.Q)
59
60#define OPTIMIZE_FRONTIER(_attach, _r_in, _r_out)                              \
61      setup.register_frontier(# _attach, _r_in, _r_out);
62
63#define RES_SWITCH(_name, _IN, _P1, _P2)                                       \
64      NET_REGISTER_DEV(RES_SWITCH, _name)                                        \
65      NET_C(_IN, _name.I)                                                    \
66      NET_C(_P1, _name.1)                                                    \
67      NET_C(_P2, _name.2)
68
69/* Default device to hold netlist parameters */
70#define PARAMETERS(_name)                                                      \
71      NET_REGISTER_DEV(PARAMETERS, _name)
72
73#define AFUNC(_name, _N, _F)                                                   \
74      NET_REGISTER_DEV(AFUNC, _name)                                      \
75      PARAM(_name.N, _N)                                                     \
76      PARAM(_name.FUNC, _F)
77
78NETLIB_NAMESPACE_DEVICES_START()
79
80// -----------------------------------------------------------------------------
81// netlistparams
82// -----------------------------------------------------------------------------
83
84NETLIB_DEVICE_WITH_PARAMS(netlistparams,
85public:
86      param_logic_t m_use_deactivate;
87);
88
89// -----------------------------------------------------------------------------
90// mainclock
91// -----------------------------------------------------------------------------
92
93NETLIB_DEVICE_WITH_PARAMS(mainclock,
94public:
95   logic_output_t m_Q;
96
97   param_double_t m_freq;
98   netlist_time m_inc;
99
100   ATTR_HOT inline static void mc_update(logic_net_t &net);
101);
102
103// -----------------------------------------------------------------------------
104// clock
105// -----------------------------------------------------------------------------
106
107NETLIB_DEVICE_WITH_PARAMS(clock,
108   logic_input_t m_feedback;
109   logic_output_t m_Q;
110
111   param_double_t m_freq;
112   netlist_time m_inc;
113);
114
115// -----------------------------------------------------------------------------
116// extclock
117// -----------------------------------------------------------------------------
118
119NETLIB_DEVICE_WITH_PARAMS(extclock,
120   logic_input_t m_feedback;
121   logic_output_t m_Q;
122
123   param_double_t m_freq;
124   param_str_t m_pattern;
125   param_double_t m_offset;
126
127   UINT8 m_cnt;
128   UINT8 m_size;
129   netlist_time m_off;
130   netlist_time m_inc[32];
131);
132
133// -----------------------------------------------------------------------------
134// Special support devices ...
135// -----------------------------------------------------------------------------
136
137NETLIB_DEVICE_WITH_PARAMS(logic_input,
138
139   virtual void stop();
140   logic_output_t m_Q;
141
142   param_logic_t m_IN;
143   param_model_t m_FAMILY;
144);
145
146NETLIB_DEVICE_WITH_PARAMS(analog_input,
147   analog_output_t m_Q;
148
149   param_double_t m_IN;
150);
151
152// -----------------------------------------------------------------------------
153// nld_gnd
154// -----------------------------------------------------------------------------
155
156class NETLIB_NAME(gnd) : public device_t
157{
158public:
159   NETLIB_NAME(gnd)()
160         : device_t(GND) { }
161
162   virtual ~NETLIB_NAME(gnd)() {}
163
164protected:
165
166   void start()
167   {
168      register_output("Q", m_Q);
169   }
170
171   void reset()
172   {
173   }
174
175   void update()
176   {
177      OUTANALOG(m_Q, 0.0);
178   }
179
180private:
181   analog_output_t m_Q;
182
183};
184
185// -----------------------------------------------------------------------------
186// nld_dummy_input
187// -----------------------------------------------------------------------------
188
189class NETLIB_NAME(dummy_input) : public device_t
190{
191public:
192   NETLIB_NAME(dummy_input)()
193         : device_t(DUMMY) { }
194
195   virtual ~NETLIB_NAME(dummy_input)() {}
196
197protected:
198
199   void start()
200   {
201      register_input("I", m_I);
202   }
203
204   void reset()
205   {
206   }
207
208   void update()
209   {
210   }
211
212private:
213   analog_input_t m_I;
214
215};
216
217// -----------------------------------------------------------------------------
218// nld_frontier
219// -----------------------------------------------------------------------------
220
221class NETLIB_NAME(frontier) : public device_t
222{
223public:
224   NETLIB_NAME(frontier)()
225         : device_t(DUMMY) { }
226
227   virtual ~NETLIB_NAME(frontier)() {}
228
229protected:
230
231   void start()
232   {
233      register_param("RIN", m_p_RIN, 1.0e6);
234      register_param("ROUT", m_p_ROUT, 50.0);
235
236      register_input("_I", m_I);
237      register_terminal("I",m_RIN.m_P);
238      register_terminal("G",m_RIN.m_N);
239      connect_late(m_I, m_RIN.m_P);
240
241      register_output("_Q", m_Q);
242      register_terminal("_OP",m_ROUT.m_P);
243      register_terminal("Q",m_ROUT.m_N);
244      connect_late(m_Q, m_ROUT.m_P);
245   }
246
247   void reset()
248   {
249      m_RIN.set(1.0 / m_p_RIN.Value(),0,0);
250      m_ROUT.set(1.0 / m_p_ROUT.Value(),0,0);
251   }
252
253   void update()
254   {
255      OUTANALOG(m_Q, INPANALOG(m_I));
256   }
257
258private:
259   NETLIB_NAME(twoterm) m_RIN;
260   NETLIB_NAME(twoterm) m_ROUT;
261   analog_input_t m_I;
262   analog_output_t m_Q;
263
264   param_double_t m_p_RIN;
265   param_double_t m_p_ROUT;
266};
267
268/* -----------------------------------------------------------------------------
269 * nld_function
270 *
271 * FIXME: Currently a proof of concept to get congo bongo working
272 * ----------------------------------------------------------------------------- */
273
274class NETLIB_NAME(function) : public device_t
275{
276public:
277   NETLIB_NAME(function)()
278         : device_t() { }
279
280   virtual ~NETLIB_NAME(function)() {}
281
282protected:
283
284   void start();
285   void reset();
286   void update();
287
288private:
289
290   enum rpn_cmd
291   {
292      ADD,
293      MULT,
294      SUB,
295      DIV,
296      PUSH_CONST,
297      PUSH_INPUT
298   };
299
300   struct rpn_inst
301   {
302      rpn_inst() : m_cmd(ADD), m_param(0.0) { }
303      rpn_cmd m_cmd;
304      nl_double m_param;
305   };
306
307   param_int_t m_N;
308   param_str_t m_func;
309   analog_output_t m_Q;
310   analog_input_t m_I[10];
311
312   plist_t<rpn_inst> m_precompiled;
313};
314
315// -----------------------------------------------------------------------------
316// nld_res_sw
317// -----------------------------------------------------------------------------
318
319class NETLIB_NAME(res_sw) : public device_t
320{
321public:
322   NETLIB_NAME(res_sw)()
323         : device_t() { }
324
325   virtual ~NETLIB_NAME(res_sw)() {}
326
327   param_double_t m_RON;
328   param_double_t m_ROFF;
329   logic_input_t m_I;
330   NETLIB_NAME(R) m_R;
331
332protected:
333
334   void start();
335   void reset();
336   ATTR_HOT void update();
337   ATTR_HOT void update_param();
338
339private:
340   UINT8 m_last_state;
341};
342
343// -----------------------------------------------------------------------------
344// nld_base_proxy
345// -----------------------------------------------------------------------------
346
347class nld_base_proxy : public device_t
348{
349public:
350   nld_base_proxy(logic_t *inout_proxied, core_terminal_t *proxy_inout)
351         : device_t()
352   {
353      m_logic_family = inout_proxied->logic_family();
354      m_term_proxied = inout_proxied;
355      m_proxy_term = proxy_inout;
356   }
357
358   virtual ~nld_base_proxy() {}
359
360   logic_t &term_proxied() const { return *m_term_proxied; }
361   core_terminal_t &proxy_term() const { return *m_proxy_term; }
362
363protected:
364
365   virtual const logic_family_desc_t &logic_family() const
366   {
367      return *m_logic_family;
368   }
369
370private:
371   const logic_family_desc_t *m_logic_family;
372   logic_t *m_term_proxied;
373   core_terminal_t *m_proxy_term;
374};
375
376// -----------------------------------------------------------------------------
377// nld_a_to_d_proxy
378// -----------------------------------------------------------------------------
379
380class nld_a_to_d_proxy : public nld_base_proxy
381{
382public:
383   nld_a_to_d_proxy(logic_input_t *in_proxied)
384         : nld_base_proxy(in_proxied, &m_I)
385   {
386   }
387
388   virtual ~nld_a_to_d_proxy() {}
389
390   analog_input_t m_I;
391   logic_output_t m_Q;
392
393protected:
394   void start()
395   {
396      register_input("I", m_I);
397      register_output("Q", m_Q);
398   }
399
400   void reset()
401   {
402   }
403
404   ATTR_HOT void update()
405   {
406      if (m_I.Q_Analog() > logic_family().m_high_thresh_V)
407         OUTLOGIC(m_Q, 1, NLTIME_FROM_NS(1));
408      else if (m_I.Q_Analog() < logic_family().m_low_thresh_V)
409         OUTLOGIC(m_Q, 0, NLTIME_FROM_NS(1));
410      else
411      {
412         // do nothing
413      }
414   }
415private:
416};
417
418// -----------------------------------------------------------------------------
419// nld_base_d_to_a_proxy
420// -----------------------------------------------------------------------------
421
422class nld_base_d_to_a_proxy : public nld_base_proxy
423{
424public:
425   virtual ~nld_base_d_to_a_proxy() {}
426
427   virtual logic_input_t &in() { return m_I; }
428
429protected:
430   nld_base_d_to_a_proxy(logic_output_t *out_proxied, core_terminal_t &proxy_out)
431         : nld_base_proxy(out_proxied, &proxy_out)
432   {
433   }
434
435   virtual void start()
436   {
437      register_input("I", m_I);
438   }
439
440   logic_input_t m_I;
441
442private:
443};
444
445class nld_d_to_a_proxy : public nld_base_d_to_a_proxy
446{
447public:
448   nld_d_to_a_proxy(logic_output_t *out_proxied)
449   : nld_base_d_to_a_proxy(out_proxied, m_RV.m_P)
450   , m_RV(TWOTERM)
451   , m_last_state(-1)
452   , m_is_timestep(false)
453   {
454   }
455
456   virtual ~nld_d_to_a_proxy() {}
457
458protected:
459   virtual void start();
460
461   virtual void reset();
462
463   ATTR_HOT void update();
464
465private:
466   analog_output_t m_Q;
467   nld_twoterm m_RV;
468   int m_last_state;
469   bool m_is_timestep;
470};
471
472
473class factory_lib_entry_t : public base_factory_t
474{
475   P_PREVENT_COPYING(factory_lib_entry_t)
476public:
477
478   ATTR_COLD factory_lib_entry_t(setup_t &setup, const pstring &name, const pstring &classname,
479         const pstring &def_param)
480   : base_factory_t(name, classname, def_param), m_setup(setup) {  }
481
482   class dummy : public device_t
483   {
484   public:
485      dummy(const pstring &dev_name) : device_t(), m_dev_name(dev_name) { }
486   protected:
487      virtual void init(netlist_t &anetlist, const pstring &aname)
488      {
489         anetlist.setup().namespace_push(aname);
490         anetlist.setup().include(m_dev_name);
491         anetlist.setup().namespace_pop();
492      }
493      void start() { }
494      void reset() { }
495      void update() { }
496
497      pstring m_dev_name;
498   };
499
500   ATTR_COLD device_t *Create()
501   {
502      device_t *r = palloc(dummy(this->name()));
503      return r;
504   }
505
506private:
507   setup_t &m_setup;
508};
509
510
511NETLIB_NAMESPACE_DEVICES_END()
512
513#endif /* NLD_SYSTEM_H_ */
trunk/src/lib/netlist/devices/nld_truthtable.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_truthtable.c
5 *
6 */
7
8#include "nld_truthtable.h"
9#include "plib/plists.h"
10
11NETLIB_NAMESPACE_DEVICES_START()
12
13unsigned truthtable_desc_t::count_bits(UINT32 v)
14{
15   unsigned ret = 0;
16   for (; v != 0; v = v >> 1)
17   {
18      if (v & 1)
19         ret++;
20   }
21   return ret;
22}
23
24UINT32 truthtable_desc_t::set_bits(UINT32 v, UINT32 b)
25{
26   UINT32 ret = 0;
27   int i = 0;
28   for (; v != 0; v = v >> 1)
29   {
30      if (v & 1)
31      {
32         ret |= ((b&1)<<i);
33         b = b >> 1;
34      }
35      i++;
36   }
37   return ret;
38}
39
40UINT32 truthtable_desc_t::get_ignored_simple(UINT32 i)
41{
42   UINT32 m_enable = 0;
43   for (UINT32 j=0; j<m_size; j++)
44   {
45      if (m_outs[j] != m_outs[i])
46      {
47         m_enable |= (i ^ j);
48      }
49   }
50   return m_enable ^ (m_size - 1);
51}
52
53UINT32 truthtable_desc_t::get_ignored_extended(UINT32 i)
54{
55   // Determine all inputs which may be ignored ...
56   UINT32 nign = 0;
57   for (unsigned j=0; j<m_NI; j++)
58   {
59      if (m_outs[i] == m_outs[i ^ (1 << j)])
60         nign |= (1<<j);
61   }
62   /* Check all permutations of ign
63    * We have to remove those where the ignored inputs
64    * may change the output
65    */
66   UINT32 bits = (1<<count_bits(nign));
67   parray_t<int> t(bits);
68
69   for (UINT32 j=1; j<bits; j++)
70   {
71      UINT32 tign = set_bits(nign, j);
72      t[j] = 0;
73      UINT32 bitsk=(1<<count_bits(tign));
74      for (UINT32 k=0; k<bitsk; k++)
75      {
76         UINT32 b=set_bits(tign, k);
77         if (m_outs[i] != m_outs[(i & ~tign) | b])
78         {
79            t[j] = 1;
80            break;
81         }
82      }
83   }
84   UINT32 jb=0;
85   UINT32 jm=0;
86   for (UINT32 j=1; j<bits; j++)
87   {
88      unsigned nb = count_bits(j);
89      if ((t[j] == 0)&& (nb>jb))
90      {
91         jb = nb;
92         jm = j;
93      }
94   }
95   return set_bits(nign, jm);
96}
97
98// ----------------------------------------------------------------------------------------
99// desc
100// ----------------------------------------------------------------------------------------
101
102void truthtable_desc_t::help(unsigned cur, pstring_list_t list,
103      UINT64 state,UINT16 val, UINT8 *timing_index)
104{
105   pstring elem = list[cur].trim();
106   int start = 0;
107   int end = 0;
108
109   if (elem.equals("0"))
110   {
111      start = 0;
112      end = 0;
113   }
114   else if (elem.equals("1"))
115   {
116      start = 1;
117      end = 1;
118   }
119   else if (elem.equals("X"))
120   {
121      start = 0;
122      end = 1;
123   }
124   else
125      nl_assert_always(false, "unknown input value (not 0, 1, or X)");
126   for (int i = start; i <= end; i++)
127   {
128      const UINT64 nstate = state | (i << cur);
129
130      if (cur < m_num_bits - 1)
131      {
132         help(cur + 1, list, nstate, val, timing_index);
133      }
134      else
135      {
136         // cutoff previous inputs and outputs for ignore
137         if (m_outs[nstate] != ~0U &&  m_outs[nstate] != val)
138            fatalerror_e(pfmt("Error in truthtable: State {1} already set, {2} != {3}\n")
139                  .x(nstate,"04")(m_outs[nstate])(val) );
140         m_outs[nstate] = val;
141         for (unsigned j=0; j<m_NO; j++)
142            m_timing[nstate * m_NO + j] = timing_index[j];
143      }
144   }
145}
146
147void truthtable_desc_t::setup(const pstring_list_t &truthtable, UINT32 disabled_ignore)
148{
149   unsigned line = 0;
150
151   if (*m_initialized)
152      return;
153
154   pstring ttline = truthtable[line];
155   line++;
156   ttline = truthtable[line];
157   line++;
158
159   for (unsigned j=0; j < m_size; j++)
160      m_outs[j] = ~0L;
161
162   for (int j=0; j < 16; j++)
163      m_timing_nt[j] = netlist_time::zero;
164
165   while (!ttline.equals(""))
166   {
167      pstring_list_t io(ttline,"|");
168      // checks
169      nl_assert_always(io.size() == 3, "io.count mismatch");
170      pstring_list_t inout(io[0], ",");
171      nl_assert_always(inout.size() == m_num_bits, "number of bits not matching");
172      pstring_list_t out(io[1], ",");
173      nl_assert_always(out.size() == m_NO, "output count not matching");
174      pstring_list_t times(io[2], ",");
175      nl_assert_always(times.size() == m_NO, "timing count not matching");
176
177      UINT16 val = 0;
178      parray_t<UINT8> tindex(m_NO);
179
180      for (unsigned j=0; j<m_NO; j++)
181      {
182         pstring outs = out[j].trim();
183         if (outs.equals("1"))
184            val = val | (1 << j);
185         else
186            nl_assert_always(outs.equals("0"), "Unknown value (not 0 or 1");
187         netlist_time t = netlist_time::from_nsec(times[j].trim().as_long());
188         int k=0;
189         while (m_timing_nt[k] != netlist_time::zero && m_timing_nt[k] != t)
190            k++;
191         m_timing_nt[k] = t;
192         tindex[j] = k;
193      }
194
195      help(0, inout, 0 , val, tindex.data());
196      ttline = truthtable[line];
197      line++;
198   }
199
200   // determine ignore
201   parray_t<UINT32> ign(m_size);
202
203   for (UINT32 j=0; j < m_size; j++)
204      ign[j] = ~0U;
205
206   for (UINT32 i=0; i<m_size; i++)
207   {
208      if (ign[i] == ~0U)
209      {
210         int tign;
211         if (0)
212         {
213            tign = get_ignored_simple(i);
214            ign[i] = tign;
215         }
216         else
217         {
218            tign = get_ignored_extended(i);
219
220            ign[i] = tign;
221            /* don't need to recalculate similar ones */
222            UINT32 bitsk=(1<<count_bits(tign));
223            for (UINT32 k=0; k<bitsk; k++)
224            {
225               UINT32 b=set_bits(tign, k);
226               ign[(i & ~tign) | b] = tign;
227            }
228         }
229      }
230   }
231   for (UINT32 i=0; i<m_size; i++)
232   {
233      if (m_outs[i] == ~0U)
234         throw fatalerror_e(pfmt("truthtable: found element not set {1}\n").x(i) );
235      m_outs[i] |= ((ign[i] & ~disabled_ignore)  << m_NO);
236   }
237   *m_initialized = true;
238
239}
240
241#define ENTRYX(_n,_m,_h)    case (_n * 1000 + _m * 10 + _h): \
242   { typedef netlist_factory_truthtable_t<_n,_m,_h> xtype; \
243      return palloc(xtype(name,classname,def_param)); } break
244
245#define ENTRYY(_n,_m)   ENTRYX(_n,_m,0); ENTRYX(_n,_m,1)
246
247#define ENTRY(_n) ENTRYY(_n, 1); ENTRYY(_n, 2); ENTRYY(_n, 3); ENTRYY(_n, 4); ENTRYY(_n, 5); ENTRYY(_n, 6)
248
249netlist_base_factory_truthtable_t *nl_tt_factory_create(const unsigned ni, const unsigned no,
250      const unsigned has_state,
251      const pstring &name, const pstring &classname,
252      const pstring &def_param)
253{
254   switch (ni * 1000 + no * 10 + has_state)
255   {
256      ENTRY(1);
257      ENTRY(2);
258      ENTRY(3);
259      ENTRY(4);
260      ENTRY(5);
261      ENTRY(6);
262      ENTRY(7);
263      ENTRY(8);
264      ENTRY(9);
265      ENTRY(10);
266      default:
267         pstring msg = pfmt("unable to create truthtable<{1},{2},{3}>")(ni)(no)(has_state);
268         nl_assert_always(false, msg);
269   }
270   return NULL;
271}
272
273NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/devices/nld_truthtable.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_truthtable.h
5 *
6 *  Created on: 19 Jun 2014
7 *      Author: andre
8 */
9
10#ifndef NLD_TRUTHTABLE_H_
11#define NLD_TRUTHTABLE_H_
12
13#include "nl_base.h"
14#include "nl_factory.h"
15
16#define NETLIB_TRUTHTABLE(_name, _nIN, _nOUT, _state)                               \
17   class NETLIB_NAME(_name) : public nld_truthtable_t<_nIN, _nOUT, _state>         \
18   {                                                                               \
19   public:                                                                         \
20      NETLIB_NAME(_name)()                                                        \
21      : nld_truthtable_t<_nIN, _nOUT, _state>(&m_ttbl, m_desc) { }                \
22   private:                                                                        \
23      static truthtable_t m_ttbl;                                                 \
24      static const char *m_desc[];                                                \
25   }
26
27#define TRUTHTABLE_START(_name, _in, _out, _has_state, _def_params) \
28   { \
29   netlist::devices::netlist_base_factory_truthtable_t *ttd = netlist::devices::nl_tt_factory_create(_in, _out, _has_state, \
30         # _name, # _name, "+" _def_params);
31
32#define TT_HEAD(_x) \
33   ttd->m_desc.add(_x);
34
35#define TT_LINE(_x) \
36   ttd->m_desc.add(_x);
37
38#define TT_FAMILY(_x) \
39   ttd->m_family = setup.family_from_model(_x);
40
41#define TRUTHTABLE_END() \
42   setup.factory().register_device(ttd); \
43   }
44
45NETLIB_NAMESPACE_DEVICES_START()
46
47#if 0
48static inline UINT32 remove_first_bit(UINT32 v)
49{
50   for (int i=0; i<32; i++)
51      if (v & (1<<i))
52         return v & ~(1<<i);
53   return v;
54}
55#endif
56
57struct truthtable_desc_t
58{
59   truthtable_desc_t(int NO, int NI, int has_state, bool *initialized,
60         UINT32 *outs, UINT8 *timing, netlist_time *timing_nt)
61   : m_NO(NO), m_NI(NI), /*m_has_state(has_state),*/ m_initialized(initialized),
62      m_outs(outs), m_timing(timing), m_timing_nt(timing_nt),
63      m_num_bits(m_NI + has_state * (m_NI + m_NO)),
64      m_size(1 << (m_num_bits))
65   {
66   }
67
68   void setup(const pstring_list_t &desc, UINT32 disabled_ignore);
69
70private:
71   void help(unsigned cur, pstring_list_t list,
72         UINT64 state,UINT16 val, UINT8 *timing_index);
73   static unsigned count_bits(UINT32 v);
74   static UINT32 set_bits(UINT32 v, UINT32 b);
75   UINT32 get_ignored_simple(UINT32 i);
76   UINT32 get_ignored_extended(UINT32 i);
77
78   unsigned m_NO;
79   unsigned m_NI;
80   //int m_has_state;
81   bool *m_initialized;
82   UINT32 *m_outs;
83   UINT8  *m_timing;
84   netlist_time *m_timing_nt;
85
86   /* additional values */
87
88   const UINT32 m_num_bits;
89   const UINT32 m_size;
90
91};
92
93template<unsigned m_NI, unsigned m_NO, int has_state>
94class nld_truthtable_t : public device_t
95{
96public:
97
98   static const int m_num_bits = m_NI + has_state * (m_NI + m_NO);
99   static const int m_size = (1 << (m_num_bits));
100
101   struct truthtable_t
102   {
103      truthtable_t() : m_initialized(false),
104            m_desc(m_NO, m_NI, has_state, &m_initialized, m_outs, m_timing, m_timing_nt) {}
105      bool m_initialized;
106      UINT32 m_outs[m_size];
107      UINT8  m_timing[m_size * m_NO];
108      netlist_time m_timing_nt[16];
109      truthtable_desc_t m_desc;
110   };
111
112   nld_truthtable_t(truthtable_t *ttbl, const char *desc[])
113   : device_t(), m_last_state(0), m_ign(0), m_active(1), m_ttp(ttbl)
114   {
115      while (*desc != NULL && **desc != 0 )
116         {
117            m_desc.add(*desc);
118            desc++;
119         }
120
121   }
122
123   nld_truthtable_t(truthtable_t *ttbl, const pstring_list_t &desc)
124   : device_t(), m_last_state(0), m_ign(0), m_active(1), m_ttp(ttbl)
125   {
126      m_desc = desc;
127   }
128
129   virtual void start()
130   {
131      pstring header = m_desc[0];
132
133      pstring_list_t io(header,"|");
134      // checks
135      nl_assert_always(io.size() == 2, "too many '|'");
136      pstring_list_t inout(io[0], ",");
137      nl_assert_always(inout.size() == m_num_bits, "bitcount wrong");
138      pstring_list_t out(io[1], ",");
139      nl_assert_always(out.size() == m_NO, "output count wrong");
140
141      for (unsigned i=0; i < m_NI; i++)
142      {
143         inout[i] = inout[i].trim();
144         register_input(inout[i], m_I[i]);
145      }
146      for (unsigned i=0; i < m_NO; i++)
147      {
148         out[i] = out[i].trim();
149         register_output(out[i], m_Q[i]);
150      }
151      // Connect output "Q" to input "_Q" if this exists
152      // This enables timed state without having explicit state ....
153      UINT32 disabled_ignore = 0;
154      for (unsigned i=0; i < m_NO; i++)
155      {
156         pstring tmp = "_" + out[i];
157         const int idx = inout.indexof(tmp);
158         if (idx>=0)
159         {
160            connect_late(m_Q[i], m_I[idx]);
161            // disable ignore for this inputs altogether.
162            // FIXME: This shouldn't be necessary
163            disabled_ignore |= (1<<idx);
164         }
165      }
166
167      m_ign = 0;
168
169      m_ttp->m_desc.setup(m_desc, disabled_ignore * 0);
170
171#if 0
172      printf("%s\n", name().cstr());
173      for (int j=0; j < m_size; j++)
174         printf("%05x %04x %04x %04x\n", j, m_ttp->m_outs[j] & ((1 << m_NO)-1),
175               m_ttp->m_outs[j] >> m_NO, m_ttp->m_timing[j * m_NO + 0]);
176      for (int k=0; m_ttp->m_timing_nt[k] != netlist_time::zero; k++)
177         printf("%d %f\n", k, m_ttp->m_timing_nt[k].as_double() * 1000000.0);
178#endif
179      save(NLNAME(m_last_state));
180      save(NLNAME(m_ign));
181      save(NLNAME(m_active));
182   }
183
184   void reset()
185   {
186      m_active = 0;
187      m_ign = 0;
188      for (unsigned i = 0; i < m_NI; i++)
189         m_I[i].activate();
190      for (unsigned i=0; i<m_NO;i++)
191         if (this->m_Q[i].net().num_cons()>0)
192            m_active++;
193      m_last_state = 0;
194   }
195
196   template<bool doOUT>
197   inline void process()
198   {
199      netlist_time mt = netlist_time::zero;
200
201      UINT32 state = 0;
202      for (unsigned i = 0; i < m_NI; i++)
203      {
204         if (!doOUT || (m_ign & (1<<i)))
205            m_I[i].activate();
206      }
207      for (unsigned i = 0; i < m_NI; i++)
208      {
209         state |= (INPLOGIC(m_I[i]) << i);
210         if (!doOUT)
211            if (this->m_I[i].net().time() > mt)
212               mt = this->m_I[i].net().time();
213      }
214
215      const UINT32 nstate = state | (has_state ? (m_last_state << m_NI) : 0);
216      const UINT32 outstate = m_ttp->m_outs[nstate];
217      const UINT32 out = outstate & ((1 << m_NO) - 1);
218      m_ign = outstate >> m_NO;
219      if (has_state)
220         m_last_state = (state << m_NO) | out;
221
222#if 0
223      for (int i = 0; i < m_NI; i++)
224         if (m_ign & (1 << i))
225            m_I[i].inactivate();
226#endif
227      const UINT32 timebase = nstate * m_NO;
228      if (doOUT)
229      {
230         for (unsigned i = 0; i < m_NO; i++)
231            OUTLOGIC(m_Q[i], (out >> i) & 1, m_ttp->m_timing_nt[m_ttp->m_timing[timebase + i]]);
232      }
233      else
234         for (unsigned i = 0; i < m_NO; i++)
235            m_Q[i].net().set_Q_time((out >> i) & 1, mt + m_ttp->m_timing_nt[m_ttp->m_timing[timebase + i]]);
236
237      if (m_NI > 1 || has_state)
238      {
239         for (unsigned i = 0; i < m_NI; i++)
240            if (m_ign & (1 << i))
241               m_I[i].inactivate();
242      }
243   }
244
245   ATTR_HOT void update()
246   {
247      process<true>();
248   }
249
250   ATTR_HOT void inc_active()
251   {
252      nl_assert(netlist().use_deactivate());
253      if (has_state == 0)
254         if (++m_active == 1)
255         {
256            process<false>();
257         }
258   }
259
260   ATTR_HOT void dec_active()
261   {
262      nl_assert(netlist().use_deactivate());
263      /* FIXME:
264       * Based on current measurements there is no point to disable
265       * 1 input devices. This should actually be a parameter so that we
266       * can decide for each individual gate whether it is benefitial to
267       * ignore deactivation.
268       */
269      if (m_NI < 2)
270         return;
271      else if (has_state == 0)
272      {
273         if (--m_active == 0)
274         {
275            for (unsigned i = 0; i< m_NI; i++)
276               m_I[i].inactivate();
277            m_ign = (1<<m_NI)-1;
278         }
279      }
280   }
281
282   logic_input_t m_I[m_NI];
283   logic_output_t m_Q[m_NO];
284
285private:
286
287   UINT32 m_last_state;
288   UINT32 m_ign;
289   INT32 m_active;
290
291   truthtable_t *m_ttp;
292   pstring_list_t m_desc;
293};
294
295class netlist_base_factory_truthtable_t : public base_factory_t
296{
297   P_PREVENT_COPYING(netlist_base_factory_truthtable_t)
298public:
299   netlist_base_factory_truthtable_t(const pstring &name, const pstring &classname,
300         const pstring &def_param)
301   : base_factory_t(name, classname, def_param), m_family(netlist_family_TTL)
302   {}
303
304   virtual ~netlist_base_factory_truthtable_t()
305   {
306      if (!m_family->m_is_static)
307         pfree(m_family);
308   }
309
310   pstring_list_t m_desc;
311   logic_family_desc_t *m_family;
312};
313
314
315template<unsigned m_NI, unsigned m_NO, int has_state>
316class netlist_factory_truthtable_t : public netlist_base_factory_truthtable_t
317{
318   P_PREVENT_COPYING(netlist_factory_truthtable_t)
319public:
320   netlist_factory_truthtable_t(const pstring &name, const pstring &classname,
321         const pstring &def_param)
322   : netlist_base_factory_truthtable_t(name, classname, def_param) { }
323
324   device_t *Create()
325   {
326      typedef nld_truthtable_t<m_NI, m_NO, has_state> tt_type;
327      device_t *r = palloc(tt_type(&m_ttbl, m_desc));
328      r->set_logic_family(m_family);
329      //r->init(setup, name);
330      return r;
331   }
332private:
333   typename nld_truthtable_t<m_NI, m_NO, has_state>::truthtable_t m_ttbl;
334};
335
336netlist_base_factory_truthtable_t *nl_tt_factory_create(const unsigned ni, const unsigned no,
337      const unsigned has_state,
338      const pstring &name, const pstring &classname,
339      const pstring &def_param);
340
341NETLIB_NAMESPACE_DEVICES_END()
342
343
344
345#endif /* NLD_TRUTHTABLE_H_ */
trunk/src/lib/netlist/macro/nlm_cd4xxx.c
r0r249195
1
2#include "nlm_cd4xxx.h"
3
4#include "devices/nld_truthtable.h"
5#include "devices/nld_system.h"
6#include "devices/nld_4020.h"
7#include "devices/nld_4066.h"
8
9/*
10 *   CD4001BC: Quad 2-Input NOR Buffered B Series Gate
11 *
12 *       +--------------+
13 *    A1 |1     ++    14| VCC
14 *    B1 |2           13| A6
15 *    A2 |3           12| Y6
16 *    Y2 |4    4001   11| A5
17 *    A3 |5           10| Y5
18 *    Y3 |6            9| A4
19 *   GND |7            8| Y4
20 *       +--------------+
21 *
22 */
23
24NETLIST_START(CD4001_DIP)
25   CD4001_NOR(s1)
26   CD4001_NOR(s2)
27   CD4001_NOR(s3)
28   CD4001_NOR(s4)
29
30   DUMMY_INPUT(VSS)
31   DUMMY_INPUT(VDD)
32
33   DIPPINS(   /*       +--------------+      */
34      s1.A,  /*    A1 |1     ++    14| VCC  */ VSS.I,
35      s1.B,  /*    B1 |2           13| A6   */ s4.B,
36      s1.Q,  /*    A2 |3           12| Y6   */ s4.A,
37      s2.Q,  /*    Y2 |4    4001   11| A5   */ s4.Q,
38      s2.A,  /*    A3 |5           10| Y5   */ s3.Q,
39      s2.B,  /*    Y3 |6            9| A4   */ s3.B,
40      VDD.I, /*   GND |7            8| Y4   */ s3.A
41            /*       +--------------+      */
42   )
43
44NETLIST_END()
45
46/*  CD4020: 14-Stage Ripple Carry Binary Counters
47 *
48 *          +--------------+
49 *      Q12 |1     ++    16| VDD
50 *      Q13 |2           15| Q11
51 *      Q14 |3           14| Q10
52 *       Q6 |4    4020   13| Q8
53 *       Q5 |5           12| Q9
54 *       Q7 |6           11| RESET
55 *       Q4 |7           10| IP (Input pulses)
56 *      VSS |8            9| Q1
57 *          +--------------+
58 *
59 *  Naming conventions follow Texas Instruments datasheet
60 *
61 *  FIXME: Timing depends on VDD-VSS
62 *         This needs a cmos d-a/a-d proxy implementation.
63 */
64
65NETLIST_START(CD4020_DIP)
66
67   CD4020(s1)
68   DIPPINS(     /*       +--------------+       */
69      s1.Q12,  /*   Q12 |1     ++    16| VDD   */ s1.VDD,
70      s1.Q13,  /*   Q13 |2           15| Q11   */ s1.Q11,
71      s1.Q14,  /*   Q14 |3           14| Q10   */ s1.Q10,
72      s1.Q6,   /*    Q6 |4    4020   13| Q8    */ s1.Q8,
73      s1.Q5,   /*    Q5 |5           12| Q9    */ s1.Q9,
74      s1.Q7,   /*    Q7 |6           11| RESET */ s1.RESET,
75      s1.Q4,   /*    Q4 |7           10| IP    */ s1.IP,
76      s1.VSS,  /*   VSS |8            9| Q1    */ s1.Q1
77               /*       +--------------+       */
78   )
79      /*
80       * IP = (Input pulses)
81       */
82
83NETLIST_END()
84
85/*  CD4066: Quad Bilateral Switch
86 *
87 *          +--------------+
88 *   INOUTA |1     ++    14| VDD
89 *   OUTINA |2           13| CONTROLA
90 *   OUTINB |3           12| CONTROLD
91 *   INOUTB |4    4066   11| INOUTD
92 * CONTROLB |5           10| OUTIND
93 * CONTROLC |6            9| OUTINC
94 *      VSS |7            8| INOUTC
95 *          +--------------+
96 *
97 *  FIXME: These devices are slow (~125 ns). THis is currently not reflected
98 *
99 *  Naming conventions follow National semiconductor datasheet
100 *
101 */
102
103NETLIST_START(CD4066_DIP)
104   CD4066_GATE(A)
105   CD4066_GATE(B)
106   CD4066_GATE(C)
107   CD4066_GATE(D)
108
109   NET_C(A.PS.VDD, B.PS.VDD, C.PS.VDD, D.PS.VDD)
110   NET_C(A.PS.VSS, B.PS.VSS, C.PS.VSS, D.PS.VSS)
111
112   PARAM(A.BASER, 270.0)
113   PARAM(B.BASER, 270.0)
114   PARAM(C.BASER, 270.0)
115   PARAM(D.BASER, 270.0)
116
117   DIPPINS(      /*          +--------------+          */
118      A.R.1,    /*   INOUTA |1     ++    14| VDD      */ A.PS.VDD,
119      A.R.2,    /*   OUTINA |2           13| CONTROLA */ A.CTL,
120      B.R.1,    /*   OUTINB |3           12| CONTROLD */ D.CTL,
121      B.R.2,    /*   INOUTB |4    4066   11| INOUTD   */ D.R.1,
122      B.CTL,    /* CONTROLB |5           10| OUTIND   */ D.R.2,
123      C.CTL,    /* CONTROLC |6            9| OUTINC   */ C.R.1,
124      A.PS.VSS, /*      VSS |7            8| INOUTC   */ C.R.2
125               /*          +--------------+          */
126   )
127NETLIST_END()
128
129NETLIST_START(CD4016_DIP)
130   CD4066_GATE(A)
131   CD4066_GATE(B)
132   CD4066_GATE(C)
133   CD4066_GATE(D)
134
135   NET_C(A.PS.VDD, B.PS.VDD, C.PS.VDD, D.PS.VDD)
136   NET_C(A.PS.VSS, B.PS.VSS, C.PS.VSS, D.PS.VSS)
137
138   PARAM(A.BASER, 1000.0)
139   PARAM(B.BASER, 1000.0)
140   PARAM(C.BASER, 1000.0)
141   PARAM(D.BASER, 1000.0)
142
143   DIPPINS(      /*          +--------------+          */
144      A.R.1,    /*   INOUTA |1     ++    14| VDD      */ A.PS.VDD,
145      A.R.2,    /*   OUTINA |2           13| CONTROLA */ A.CTL,
146      B.R.1,    /*   OUTINB |3           12| CONTROLD */ D.CTL,
147      B.R.2,    /*   INOUTB |4    4016   11| INOUTD   */ D.R.1,
148      B.CTL,    /* CONTROLB |5           10| OUTIND   */ D.R.2,
149      C.CTL,    /* CONTROLC |6            9| OUTINC   */ C.R.1,
150      A.PS.VSS, /*      VSS |7            8| INOUTC   */ C.R.2
151               /*          +--------------+          */
152   )
153NETLIST_END()
154
155NETLIST_START(CD4XXX_lib)
156
157   TRUTHTABLE_START(CD4001_NOR, 2, 1, 0, "")
158      TT_HEAD("A , B | Q ")
159      TT_LINE("0,0|1|85")
160      TT_LINE("X,1|0|120")
161      TT_LINE("1,X|0|120")
162      TT_FAMILY("CD4XXX")
163   TRUTHTABLE_END()
164
165   LOCAL_LIB_ENTRY(CD4001_DIP)
166
167   /* DIP ONLY */
168   LOCAL_LIB_ENTRY(CD4020_DIP)
169   LOCAL_LIB_ENTRY(CD4016_DIP)
170   LOCAL_LIB_ENTRY(CD4066_DIP)
171
172NETLIST_END()
trunk/src/lib/netlist/macro/nlm_cd4xxx.h
r0r249195
1#ifndef NLD_CD4XXX_H_
2#define NLD_CD4XXX_H_
3
4#include "nl_setup.h"
5
6/*
7 * Devices:
8 *
9 * CD4001_NOR : single gate
10 * CD4001_DIP : dip package
11 * CD4020_DIP : dip package (device model in core)
12 * CD4016_DIP : dip package (device model in core)
13 * CD4066_DIP : dip package (device model in core)
14 *
15 */
16
17#ifndef __PLIB_PREPROCESSOR__
18
19/* ----------------------------------------------------------------------------
20 *  Netlist Macros
21 * ---------------------------------------------------------------------------*/
22
23#define CD4001_NOR(_name)                                                      \
24      NET_REGISTER_DEV(CD4001_NOR, _name)
25
26#define CD4001_DIP(_name)                                                      \
27      NET_REGISTER_DEV(CD4001_DIP, _name)
28
29/* ----------------------------------------------------------------------------
30 *  DIP only macros
31 * ---------------------------------------------------------------------------*/
32
33#define CD4020_DIP(_name)                                                      \
34      NET_REGISTER_DEV(CD4020_DIP, _name)
35
36#define CD4066_DIP(_name)                                                      \
37      NET_REGISTER_DEV(CD4066_DIP, _name)
38
39#define CD4016_DIP(_name)                                                      \
40      NET_REGISTER_DEV(CD4016_DIP, _name)
41
42/* ----------------------------------------------------------------------------
43 *  External declarations
44 * ---------------------------------------------------------------------------*/
45
46NETLIST_EXTERNAL(CD4XXX_lib)
47
48#endif
49
50#endif
trunk/src/lib/netlist/macro/nlm_opamp.c
r0r249195
1
2#include "nlm_opamp.h"
3
4#include "analog/nld_opamps.h"
5#include "devices/nld_system.h"
6
7/*
8 *   Generic layout with 4 opamps, VCC on pint 4 and GND on pin 11
9 */
10
11NETLIST_START(opamp_layout_4_4_11)
12   DIPPINS(      /*   +--------------+   */
13      A.OUT,    /*   |1     ++    14|   */ D.OUT,
14      A.MINUS,  /*   |2           13|   */ D.MINUS,
15      A.PLUS,   /*   |3           12|   */ D.PLUS,
16      A.VCC,    /*   |4           11|   */ A.GND,
17      B.PLUS,   /*   |5           10|   */ C.PLUS,
18      B.MINUS,  /*   |6            9|   */ C.MINUS,
19      B.OUT,    /*   |7            8|   */ C.OUT
20               /*   +--------------+   */
21   )
22   NET_C(A.GND, B.GND, C.GND, D.GND)
23   NET_C(A.VCC, B.VCC, C.VCC, D.VCC)
24NETLIST_END()
25
26/*
27 *   Generic layout with 2 opamps, VCC on pint 8 and GND on pin 4
28 */
29
30NETLIST_START(opamp_layout_2_8_4)
31   DIPPINS(      /*   +--------------+   */
32      A.OUT,    /*   |1     ++     8|   */ A.VCC,
33      A.MINUS,  /*   |2            7|   */ B.OUT,
34      A.PLUS,   /*   |3            6|   */ B.MINUS,
35      A.GND,    /*   |4            5|   */ B.PLUS
36               /*   +--------------+   */
37   )
38   NET_C(A.GND, B.GND)
39   NET_C(A.VCC, B.VCC)
40NETLIST_END()
41
42NETLIST_START(MB3614_DIP)
43   OPAMP(A, "MB3614")
44   OPAMP(B, "MB3614")
45   OPAMP(C, "MB3614")
46   OPAMP(D, "MB3614")
47
48   INCLUDE(opamp_layout_4_4_11)
49
50NETLIST_END()
51
52NETLIST_START(LM324_DIP)
53   OPAMP(A, "LM324")
54   OPAMP(B, "LM324")
55   OPAMP(C, "LM324")
56   OPAMP(D, "LM324")
57
58   INCLUDE(opamp_layout_4_4_11)
59
60NETLIST_END()
61
62NETLIST_START(LM358_DIP)
63   OPAMP(A, "LM358")
64   OPAMP(B, "LM358")
65
66   INCLUDE(opamp_layout_2_8_4)
67
68NETLIST_END()
69
70NETLIST_START(OPAMP_lib)
71   LOCAL_LIB_ENTRY(opamp_layout_4_4_11)
72   LOCAL_LIB_ENTRY(opamp_layout_2_8_4)
73
74   NET_MODEL("LM324       OPAMP(TYPE=3 VLH=2.0 VLL=0.2 FPF=5 UGF=500k SLEW=0.3M RI=1000k RO=50 DAB=0.00075)")
75   NET_MODEL("LM358       OPAMP(TYPE=3 VLH=2.0 VLL=0.2 FPF=5 UGF=500k SLEW=0.3M RI=1000k RO=50 DAB=0.001)")
76   NET_MODEL("MB3614      OPAMP(TYPE=3 VLH=1.4 VLL=0.02 FPF=2 UGF=500k SLEW=0.6M RI=1000k RO=50 DAB=0.0002)")
77
78   LOCAL_LIB_ENTRY(MB3614_DIP)
79   LOCAL_LIB_ENTRY(LM324_DIP)
80   LOCAL_LIB_ENTRY(LM358_DIP)
81
82
83NETLIST_END()
trunk/src/lib/netlist/macro/nlm_opamp.h
r0r249195
1#ifndef NLM_OPAMP_H_
2#define NLM_OPAMP_H_
3
4#include "nl_setup.h"
5
6#ifndef __PLIB_PREPROCESSOR__
7
8/* ----------------------------------------------------------------------------
9 *  Netlist Macros
10 * ---------------------------------------------------------------------------*/
11
12#define MB3614_DIP(_name)                                                      \
13      NET_REGISTER_DEV(MB3614_DIP, _name)
14
15#define LM324_DIP(_name)                                                       \
16      NET_REGISTER_DEV(LM324_DIP, _name)
17
18#define LM358_DIP(_name)                                                       \
19      NET_REGISTER_DEV(LM358_DIP, _name)
20
21/* ----------------------------------------------------------------------------
22 *  External declarations
23 * ---------------------------------------------------------------------------*/
24
25NETLIST_EXTERNAL(OPAMP_lib)
26
27#endif
28
29#endif
trunk/src/lib/netlist/macro/nlm_other.c
r0r249195
1
2#include "nlm_other.h"
3
4#include "devices/nld_truthtable.h"
5#include "devices/nld_system.h"
6
7/*
8 *   MC14584B: Hex Schmitt Trigger
9 *             ON Semiconductor
10 *
11 *          +--------------+
12 *       A1 |1     ++    14| VCC
13 *       Y1 |2           13| A6
14 *       A2 |3           12| Y6
15 *       Y2 |4  MC14584B 11| A5
16 *       A3 |5           10| Y5
17 *       Y3 |6            9| A4
18 *      GND |7            8| Y4
19 *          +--------------+
20 *
21 */
22
23NETLIST_START(MC14584B_DIP)
24   MC14584B_GATE(s1)
25   MC14584B_GATE(s2)
26   MC14584B_GATE(s3)
27   MC14584B_GATE(s4)
28   MC14584B_GATE(s5)
29   MC14584B_GATE(s6)
30
31   DUMMY_INPUT(GND)
32   DUMMY_INPUT(VCC)
33
34   DIPPINS(   /*       +--------------+      */
35      s1.A,  /*    A1 |1     ++    14| VCC  */ VCC.I,
36      s1.Q,  /*    Y1 |2           13| A6   */ s6.A,
37      s2.A,  /*    A2 |3           12| Y6   */ s6.Q,
38      s2.Q,  /*    Y2 |4    7416   11| A5   */ s5.A,
39      s3.A,  /*    A3 |5           10| Y5   */ s5.Q,
40      s3.Q,  /*    Y3 |6            9| A4   */ s4.A,
41      GND.I, /*   GND |7            8| Y4   */ s4.Q
42            /*       +--------------+      */
43   )
44NETLIST_END()
45
46NETLIST_START(otheric_lib)
47   TRUTHTABLE_START(MC14584B_GATE, 1, 1, 0, "")
48      TT_HEAD(" A | Q ")
49      TT_LINE(" 0 | 1 |100")
50      TT_LINE(" 1 | 0 |100")
51      TT_FAMILY("FAMILY(IVL=2.1 IVH=2.7 OVL=0.05 OVH=4.95 ORL=10.0 ORH=10.0)")
52   TRUTHTABLE_END()
53
54   LOCAL_LIB_ENTRY(MC14584B_DIP)
55NETLIST_END()
trunk/src/lib/netlist/macro/nlm_other.h
r0r249195
1#ifndef NLM_OTHER_H_
2#define NLM_OTHER_H_
3
4#include "nl_setup.h"
5
6#ifndef __PLIB_PREPROCESSOR__
7
8/* ----------------------------------------------------------------------------
9 *  Netlist Macros
10 * ---------------------------------------------------------------------------*/
11
12#define MC14584B_GATE(_name)                                                   \
13      NET_REGISTER_DEV(MC14584B_GATE, _name)
14
15#define MC14584B_DIP(_name)                                                    \
16      NET_REGISTER_DEV(MC14584B_DIP, _name)
17
18
19/* ----------------------------------------------------------------------------
20 *  External declarations
21 * ---------------------------------------------------------------------------*/
22
23NETLIST_EXTERNAL(otheric_lib)
24
25#endif
26
27#endif
trunk/src/lib/netlist/macro/nlm_ttl74xx.c
r0r249195
1
2#include "nlm_ttl74xx.h"
3
4#include "devices/nld_truthtable.h"
5#include "devices/nld_system.h"
6
7/*
8 *   DM7416: Hex Inverting Buffers with
9 *           High Voltage Open-Collector Outputs
10 *
11 *          +--------------+
12 *       A1 |1     ++    14| VCC
13 *       Y1 |2           13| A6
14 *       A2 |3           12| Y6
15 *       Y2 |4    7416   11| A5
16 *       A3 |5           10| Y5
17 *       Y3 |6            9| A4
18 *      GND |7            8| Y4
19 *          +--------------+
20 *
21 */
22
23NETLIST_START(TTL_7416_DIP)
24   TTL_7416_GATE(s1)
25   TTL_7416_GATE(s2)
26   TTL_7416_GATE(s3)
27   TTL_7416_GATE(s4)
28   TTL_7416_GATE(s5)
29   TTL_7416_GATE(s6)
30
31   DUMMY_INPUT(GND)
32   DUMMY_INPUT(VCC)
33
34   DIPPINS(   /*       +--------------+      */
35      s1.A,  /*    A1 |1     ++    14| VCC  */ VCC.I,
36      s1.Q,  /*    Y1 |2           13| A6   */ s6.A,
37      s2.A,  /*    A2 |3           12| Y6   */ s6.Q,
38      s2.Q,  /*    Y2 |4    7416   11| A5   */ s5.A,
39      s3.A,  /*    A3 |5           10| Y5   */ s5.Q,
40      s3.Q,  /*    Y3 |6            9| A4   */ s4.A,
41      GND.I, /*   GND |7            8| Y4   */ s4.Q
42            /*       +--------------+      */
43   )
44NETLIST_END()
45
46NETLIST_START(TTL74XX_lib)
47   TRUTHTABLE_START(TTL_7416_GATE, 1, 1, 0, "")
48      TT_HEAD(" A | Q ")
49      TT_LINE(" 0 | 1 |15")
50      TT_LINE(" 1 | 0 |23")
51      /* Open Collector */
52      TT_FAMILY("74XXOC")
53   TRUTHTABLE_END()
54
55   LOCAL_LIB_ENTRY(TTL_7416_DIP)
56NETLIST_END()
trunk/src/lib/netlist/macro/nlm_ttl74xx.h
r0r249195
1#ifndef NLD_TTL74XX_H_
2#define NLD_TTL74XX_H_
3
4#include "nl_setup.h"
5
6#ifndef __PLIB_PREPROCESSOR__
7
8/* ----------------------------------------------------------------------------
9 *  Netlist Macros
10 * ---------------------------------------------------------------------------*/
11
12#define TTL_7416_GATE(_name)                                                   \
13      NET_REGISTER_DEV(TTL_7416_GATE, _name)
14
15#define TTL_7416_DIP(_name)                                                    \
16      NET_REGISTER_DEV(TTL7416_DIP, _name)
17
18/* ----------------------------------------------------------------------------
19 *  External declarations
20 * ---------------------------------------------------------------------------*/
21
22NETLIST_EXTERNAL(TTL74XX_lib)
23
24#endif
25
26#endif
trunk/src/lib/netlist/nl_base.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nlbase.c
5 *
6 */
7
8#include <solver/nld_solver.h>
9#include <cstring>
10#include <algorithm>
11
12#include "plib/palloc.h"
13
14#include "nl_base.h"
15#include "devices/nld_system.h"
16#include "nl_util.h"
17
18const netlist::netlist_time netlist::netlist_time::zero = netlist::netlist_time::from_raw(0);
19
20namespace netlist
21{
22// ----------------------------------------------------------------------------------------
23// logic_family_ttl_t
24// ----------------------------------------------------------------------------------------
25
26class logic_family_ttl_t : public logic_family_desc_t
27{
28public:
29   logic_family_ttl_t() : logic_family_desc_t()
30   {
31      m_low_thresh_V = 0.8;
32      m_high_thresh_V = 2.0;
33      // m_low_V  - these depend on sinked/sourced current. Values should be suitable for typical applications.
34      m_low_V = 0.1;
35      m_high_V = 4.0;
36      m_R_low = 1.0;
37      m_R_high = 130.0;
38      m_is_static = true;
39   }
40   virtual devices::nld_base_d_to_a_proxy *create_d_a_proxy(logic_output_t *proxied) const
41   {
42      return palloc(devices::nld_d_to_a_proxy(proxied));
43   }
44};
45
46//FIXME: set to proper values
47class logic_family_cd4xxx_t : public logic_family_desc_t
48{
49public:
50   logic_family_cd4xxx_t() : logic_family_desc_t()
51   {
52      m_low_thresh_V = 0.8;
53      m_high_thresh_V = 2.0;
54      // m_low_V  - these depend on sinked/sourced current. Values should be suitable for typical applications.
55      m_low_V = 0.05;
56      m_high_V = 4.95;
57      m_R_low = 10.0;
58      m_R_high = 10.0;
59      m_is_static = true;
60   }
61   virtual devices::nld_base_d_to_a_proxy *create_d_a_proxy(logic_output_t *proxied) const
62   {
63      return palloc(devices::nld_d_to_a_proxy(proxied));
64   }
65};
66
67logic_family_desc_t *netlist_family_TTL = palloc(logic_family_ttl_t);
68logic_family_desc_t *netlist_family_CD4XXX = palloc(logic_family_cd4xxx_t);
69
70// ----------------------------------------------------------------------------------------
71// netlist_queue_t
72// ----------------------------------------------------------------------------------------
73
74queue_t::queue_t(netlist_t &nl)
75   : timed_queue<net_t *, netlist_time>(512)
76   , object_t(QUEUE, GENERIC)
77   , pstate_callback_t()
78   , m_qsize(0)
79   , m_times(512)
80   , m_names(512)
81{
82   this->init_object(nl, "QUEUE");
83}
84
85void queue_t::register_state(pstate_manager_t &manager, const pstring &module)
86{
87   netlist().log().debug("register_state\n");
88   manager.save_item(m_qsize, this, module + "." + "qsize");
89   manager.save_item(&m_times[0], this, module + "." + "times", m_times.size());
90   manager.save_item(&(m_names[0].m_buf[0]), this, module + "." + "names", m_names.size() * sizeof(names_t));
91}
92
93void queue_t::on_pre_save()
94{
95   netlist().log().debug("on_pre_save\n");
96   m_qsize = this->count();
97   netlist().log().debug("current time {1} qsize {2}\n", netlist().time().as_double(), m_qsize);
98   for (int i = 0; i < m_qsize; i++ )
99   {
100      m_times[i] =  this->listptr()[i].exec_time().as_raw();
101      pstring p = this->listptr()[i].object()->name();
102      int n = p.len();
103      n = std::min(63, n);
104      std::strncpy(m_names[i].m_buf, p.cstr(), n);
105      m_names[i].m_buf[n] = 0;
106   }
107}
108
109
110void queue_t::on_post_load()
111{
112   this->clear();
113   netlist().log().debug("current time {1} qsize {2}\n", netlist().time().as_double(), m_qsize);
114   for (int i = 0; i < m_qsize; i++ )
115   {
116      net_t *n = netlist().find_net(m_names[i].m_buf);
117      //log().debug("Got {1} ==> {2}\n", qtemp[i].m_name, n));
118      //log().debug("schedule time {1} ({2})\n", n->time().as_double(),  netlist_time::from_raw(m_times[i]).as_double()));
119      this->push(queue_t::entry_t(netlist_time::from_raw(m_times[i]), n));
120   }
121}
122
123// ----------------------------------------------------------------------------------------
124// netlist_object_t
125// ----------------------------------------------------------------------------------------
126
127ATTR_COLD object_t::object_t(const type_t atype, const family_t afamily)
128: m_objtype(atype)
129, m_family(afamily)
130, m_netlist(NULL)
131{}
132
133ATTR_COLD object_t::~object_t()
134{
135}
136
137ATTR_COLD void object_t::init_object(netlist_t &nl, const pstring &aname)
138{
139   m_netlist = &nl;
140   m_name = aname;
141   save_register();
142}
143
144ATTR_COLD const pstring &object_t::name() const
145{
146   if (m_name == "")
147      netlist().log().fatal("object not initialized");
148   return m_name;
149}
150
151// ----------------------------------------------------------------------------------------
152// netlist_owned_object_t
153// ----------------------------------------------------------------------------------------
154
155ATTR_COLD device_object_t::device_object_t(const type_t atype,
156      const family_t afamily)
157: object_t(atype, afamily)
158, m_device(NULL)
159{
160}
161
162ATTR_COLD void device_object_t::init_object(core_device_t &dev,
163      const pstring &aname)
164{
165   object_t::init_object(dev.netlist(), aname);
166   m_device = &dev;
167}
168
169// ----------------------------------------------------------------------------------------
170// netlist_base_t
171// ----------------------------------------------------------------------------------------
172
173netlist_t::netlist_t()
174   :   object_t(NETLIST, GENERIC), pstate_manager_t(),
175      m_stop(netlist_time::zero),
176      m_time(netlist_time::zero),
177      m_use_deactivate(0),
178      m_queue(*this),
179      m_mainclock(NULL),
180      m_solver(NULL),
181      m_gnd(NULL),
182      m_setup(NULL),
183      m_log(this)
184{
185}
186
187netlist_t::~netlist_t()
188{
189   for (std::size_t i=0; i < m_nets.size(); i++)
190   {
191      if (!m_nets[i]->isRailNet())
192      {
193         pfree(m_nets[i]);
194      }
195   }
196
197   m_nets.clear();
198
199   m_devices.clear_and_free();
200
201   pstring::resetmem();
202}
203
204ATTR_COLD void netlist_t::save_register()
205{
206   save(static_cast<pstate_callback_t &>(m_queue), "m_queue");
207   save(NLNAME(m_time));
208   object_t::save_register();
209}
210
211ATTR_HOT nl_double netlist_t::gmin() const
212{
213   return solver()->gmin();
214}
215
216ATTR_COLD void netlist_t::start()
217{
218   /* find the main clock and solver ... */
219
220   log().debug("Searching for mainclock and solver ...\n");
221
222   m_mainclock = get_single_device<devices:: NETLIB_NAME(mainclock)>("mainclock");
223   m_solver = get_single_device<devices::NETLIB_NAME(solver)>("solver");
224   m_gnd = get_single_device<devices::NETLIB_NAME(gnd)>("gnd");
225   m_params = get_single_device<devices::NETLIB_NAME(netlistparams)>("parameter");
226
227   /* make sure the solver and parameters are started first! */
228
229   if (m_solver != NULL)
230      m_solver->start_dev();
231
232   if (m_params != NULL)
233   {
234      m_params->start_dev();
235   }
236
237   m_use_deactivate = (m_params->m_use_deactivate.Value() ? true : false);
238
239   log().debug("Initializing devices ...\n");
240   for (std::size_t i = 0; i < m_devices.size(); i++)
241   {
242      device_t *dev = m_devices[i];
243      if (dev != m_solver && dev != m_params)
244         dev->start_dev();
245   }
246
247}
248
249ATTR_COLD void netlist_t::stop()
250{
251   /* find the main clock and solver ... */
252
253   log().debug("Stopping all devices ...\n");
254
255   // Step all devices once !
256   for (std::size_t i = 0; i < m_devices.size(); i++)
257   {
258      m_devices[i]->stop_dev();
259   }
260}
261
262ATTR_COLD net_t *netlist_t::find_net(const pstring &name)
263{
264   for (std::size_t i = 0; i < m_nets.size(); i++)
265   {
266      if (m_nets[i]->name() == name)
267         return m_nets[i];
268   }
269   return NULL;
270}
271
272ATTR_COLD void netlist_t::rebuild_lists()
273{
274   //printf("Rebuild Lists\n");
275   for (std::size_t i = 0; i < m_nets.size(); i++)
276      m_nets[i]->rebuild_list();
277}
278
279
280ATTR_COLD void netlist_t::reset()
281{
282   m_time = netlist_time::zero;
283   m_queue.clear();
284   if (m_mainclock != NULL)
285      m_mainclock->m_Q.net().set_time(netlist_time::zero);
286   if (m_solver != NULL)
287      m_solver->do_reset();
288
289   // Reset all nets once !
290   for (std::size_t i = 0; i < m_nets.size(); i++)
291      m_nets[i]->do_reset();
292
293   // Reset all devices once !
294   for (std::size_t i = 0; i < m_devices.size(); i++)
295   {
296      m_devices[i]->do_reset();
297   }
298
299   // Step all devices once !
300   for (std::size_t i = 0; i < m_devices.size(); i++)
301   {
302      m_devices[i]->update_dev();
303   }
304
305   // FIXME: some const devices rely on this
306   /* make sure params are set now .. */
307   for (std::size_t i = 0; i < m_devices.size(); i++)
308   {
309      m_devices[i]->update_param();
310   }
311}
312
313
314ATTR_HOT void netlist_t::process_queue(const netlist_time &delta)
315{
316   m_stop = m_time + delta;
317
318   if (m_mainclock == NULL)
319   {
320      while ( (m_time < m_stop) && (m_queue.is_not_empty()))
321      {
322         const queue_t::entry_t e = *m_queue.pop();
323         m_time = e.exec_time();
324         e.object()->update_devs();
325
326         add_to_stat(m_perf_out_processed, 1);
327      }
328      if (m_queue.is_empty())
329         m_time = m_stop;
330
331   } else {
332      logic_net_t &mc_net = m_mainclock->m_Q.net().as_logic();
333      const netlist_time inc = m_mainclock->m_inc;
334      netlist_time mc_time = mc_net.time();
335
336      while (m_time < m_stop)
337      {
338         if (m_queue.is_not_empty())
339         {
340            while (m_queue.peek()->exec_time() > mc_time)
341            {
342               m_time = mc_time;
343               mc_time += inc;
344               devices::NETLIB_NAME(mainclock)::mc_update(mc_net);
345            }
346
347            const queue_t::entry_t e = *m_queue.pop();
348            m_time = e.exec_time();
349            e.object()->update_devs();
350
351         } else {
352            m_time = mc_time;
353            mc_time += inc;
354            devices::NETLIB_NAME(mainclock)::mc_update(mc_net);
355         }
356
357         add_to_stat(m_perf_out_processed, 1);
358      }
359      mc_net.set_time(mc_time);
360   }
361}
362
363// ----------------------------------------------------------------------------------------
364// Default netlist elements ...
365// ----------------------------------------------------------------------------------------
366
367
368
369// ----------------------------------------------------------------------------------------
370// net_core_device_t
371// ----------------------------------------------------------------------------------------
372
373ATTR_COLD core_device_t::core_device_t(const family_t afamily)
374: object_t(DEVICE, afamily), logic_family_t()
375#if (NL_KEEP_STATISTICS)
376   , stat_total_time(0)
377   , stat_update_count(0)
378   , stat_call_count(0)
379#endif
380{
381}
382
383ATTR_COLD void core_device_t::init(netlist_t &anetlist, const pstring &name)
384{
385   if (logic_family() == NULL)
386      set_logic_family(this->default_logic_family());
387   init_object(anetlist, name);
388
389#if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF)
390   void (core_device_t::* pFunc)() = &core_device_t::update;
391   m_static_update = pFunc;
392#elif (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV)
393   void (core_device_t::* pFunc)() = &core_device_t::update;
394   m_static_update = reinterpret_cast<net_update_delegate>((this->*pFunc));
395#elif (NL_PMF_TYPE == NL_PMF_TYPE_INTERNAL)
396   m_static_update = pmfp::get_mfp<net_update_delegate>(&core_device_t::update, this);
397#endif
398}
399
400ATTR_COLD core_device_t::~core_device_t()
401{
402}
403
404ATTR_COLD void core_device_t::start_dev()
405{
406#if (NL_KEEP_STATISTICS)
407   netlist().m_started_devices.add(this, false);
408#endif
409   start();
410}
411
412ATTR_COLD void core_device_t::stop_dev()
413{
414#if (NL_KEEP_STATISTICS)
415#endif
416   stop();
417}
418
419ATTR_HOT netlist_sig_t core_device_t::INPLOGIC_PASSIVE(logic_input_t &inp)
420{
421   if (inp.state() != logic_t::STATE_INP_PASSIVE)
422      return inp.Q();
423   else
424   {
425      inp.activate();
426      const netlist_sig_t ret = inp.Q();
427      inp.inactivate();
428      return ret;
429   }
430}
431
432
433// ----------------------------------------------------------------------------------------
434// netlist_device_t
435// ----------------------------------------------------------------------------------------
436
437device_t::device_t()
438   : core_device_t(GENERIC),
439      m_terminals(20)
440{
441}
442
443device_t::device_t(const family_t afamily)
444   : core_device_t(afamily),
445      m_terminals(20)
446{
447}
448
449device_t::~device_t()
450{
451   //log().debug("~net_device_t\n");
452}
453
454ATTR_COLD setup_t &device_t::setup()
455{
456   return netlist().setup();
457}
458
459ATTR_COLD void device_t::init(netlist_t &anetlist, const pstring &name)
460{
461   core_device_t::init(anetlist, name);
462}
463
464
465ATTR_COLD void device_t::register_sub(const pstring &name, device_t &dev)
466{
467   dev.init(netlist(), this->name() + "." + name);
468   // subdevices always first inherit the logic family of the parent
469   dev.set_logic_family(this->logic_family());
470   dev.start_dev();
471}
472
473ATTR_COLD void device_t::register_subalias(const pstring &name, core_terminal_t &term)
474{
475   pstring alias = this->name() + "." + name;
476
477   // everything already fully qualified
478   setup().register_alias_nofqn(alias, term.name());
479
480   if (term.isType(terminal_t::INPUT) || term.isType(terminal_t::TERMINAL))
481      m_terminals.add(alias);
482}
483
484ATTR_COLD void device_t::register_subalias(const pstring &name, const pstring &aliased)
485{
486   pstring alias = this->name() + "." + name;
487   pstring aliased_fqn = this->name() + "." + aliased;
488
489   // everything already fully qualified
490   setup().register_alias_nofqn(alias, aliased_fqn);
491
492   // FIXME: make this working again
493   //if (term.isType(terminal_t::INPUT) || term.isType(terminal_t::TERMINAL))
494   //  m_terminals.add(name);
495}
496
497ATTR_COLD void device_t::register_terminal(const pstring &name, terminal_t &port)
498{
499   setup().register_object(*this, name, port);
500   if (port.isType(terminal_t::INPUT) || port.isType(terminal_t::TERMINAL))
501      m_terminals.add(port.name());
502}
503
504ATTR_COLD void device_t::register_output(const pstring &name, logic_output_t &port)
505{
506   port.set_logic_family(this->logic_family());
507   setup().register_object(*this, name, port);
508}
509
510ATTR_COLD void device_t::register_output(const pstring &name, analog_output_t &port)
511{
512   setup().register_object(*this, name, port);
513}
514
515ATTR_COLD void device_t::register_input(const pstring &name, logic_input_t &inp)
516{
517   inp.set_logic_family(this->logic_family());
518   setup().register_object(*this, name, inp);
519   m_terminals.add(inp.name());
520}
521
522ATTR_COLD void device_t::register_input(const pstring &name, analog_input_t &inp)
523{
524   setup().register_object(*this, name, inp);
525   m_terminals.add(inp.name());
526}
527
528ATTR_COLD void device_t::connect_late(core_terminal_t &t1, core_terminal_t &t2)
529{
530   setup().register_link_fqn(t1.name(), t2.name());
531}
532
533ATTR_COLD void device_t::connect_late(const pstring &t1, const pstring &t2)
534{
535   setup().register_link_fqn(name() + "." + t1, name() + "." + t2);
536}
537
538ATTR_COLD void device_t::connect_direct(core_terminal_t &t1, core_terminal_t &t2)
539{
540   if (!setup().connect(t1, t2))
541      netlist().log().fatal("Error connecting {1} to {2}\n", t1.name(), t2.name());
542}
543
544
545template <class C, class T>
546ATTR_COLD void device_t::register_param(const pstring &sname, C &param, const T initialVal)
547{
548   pstring fullname = this->name() + "." + sname;
549   param.init_object(*this, fullname);
550   param.initial(initialVal);
551   setup().register_object(*this, fullname, param);
552}
553
554template ATTR_COLD void device_t::register_param(const pstring &sname, param_double_t &param, const double initialVal);
555template ATTR_COLD void device_t::register_param(const pstring &sname, param_double_t &param, const float initialVal);
556template ATTR_COLD void device_t::register_param(const pstring &sname, param_int_t &param, const int initialVal);
557template ATTR_COLD void device_t::register_param(const pstring &sname, param_logic_t &param, const int initialVal);
558template ATTR_COLD void device_t::register_param(const pstring &sname, param_str_t &param, const char * const initialVal);
559template ATTR_COLD void device_t::register_param(const pstring &sname, param_str_t &param, const pstring &initialVal);
560template ATTR_COLD void device_t::register_param(const pstring &sname, param_model_t &param, const char * const initialVal);
561
562
563// ----------------------------------------------------------------------------------------
564// netlist_net_t
565// ----------------------------------------------------------------------------------------
566
567ATTR_COLD net_t::net_t(const family_t afamily)
568   : object_t(NET, afamily)
569   , m_new_Q(0)
570   , m_cur_Q (0)
571   , m_railterminal(NULL)
572   , m_time(netlist_time::zero)
573   , m_active(0)
574   , m_in_queue(2)
575   , m_cur_Analog(0.0)
576{
577}
578
579ATTR_COLD net_t::~net_t()
580{
581   if (isInitialized())
582      netlist().remove_save_items(this);
583}
584
585ATTR_COLD void net_t::init_object(netlist_t &nl, const pstring &aname)
586{
587   object_t::init_object(nl, aname);
588   nl.m_nets.add(this);
589}
590
591ATTR_HOT void net_t::inc_active(core_terminal_t &term)
592{
593   m_active++;
594   m_list_active.insert(term);
595   nl_assert(m_active <= num_cons());
596   if (m_active == 1)
597   {
598      if (netlist().use_deactivate())
599      {
600         railterminal().device().inc_active();
601         //m_cur_Q = m_new_Q;
602      }
603      if (m_in_queue == 0)
604      {
605         if (m_time > netlist().time())
606         {
607            m_in_queue = 1;     /* pending */
608            netlist().push_to_queue(*this, m_time);
609         }
610         else
611         {
612            m_cur_Q = m_new_Q;
613            m_in_queue = 2;
614         }
615      }
616      //else if (netlist().use_deactivate())
617      //  m_cur_Q = m_new_Q;
618   }
619}
620
621ATTR_HOT void net_t::dec_active(core_terminal_t &term)
622{
623   m_active--;
624   nl_assert(m_active >= 0);
625   m_list_active.remove(term);
626   if (m_active == 0 && netlist().use_deactivate())
627         railterminal().device().dec_active();
628}
629
630ATTR_COLD void net_t::register_railterminal(core_terminal_t &mr)
631{
632   nl_assert(m_railterminal == NULL);
633   m_railterminal = &mr;
634}
635
636ATTR_COLD void net_t::rebuild_list()
637{
638   /* rebuild m_list */
639
640   unsigned cnt = 0;
641   m_list_active.clear();
642   for (std::size_t i=0; i < m_core_terms.size(); i++)
643      if (m_core_terms[i]->state() != logic_t::STATE_INP_PASSIVE)
644      {
645         m_list_active.add(*m_core_terms[i]);
646         cnt++;
647      }
648   m_active = cnt;
649}
650
651ATTR_COLD void net_t::save_register()
652{
653   save(NLNAME(m_time));
654   save(NLNAME(m_active));
655   save(NLNAME(m_in_queue));
656   save(NLNAME(m_cur_Analog));
657   save(NLNAME(m_cur_Q));
658   save(NLNAME(m_new_Q));
659   object_t::save_register();
660}
661
662ATTR_HOT /* inline */ void core_terminal_t::update_dev(const UINT32 mask)
663{
664   inc_stat(netdev().stat_call_count);
665   if ((state() & mask) != 0)
666   {
667      device().update_dev();
668   }
669}
670
671ATTR_HOT /* inline */ void net_t::update_devs()
672{
673   //assert(m_num_cons != 0);
674   nl_assert(this->isRailNet());
675
676   const UINT32 masks[4] = { 1, 5, 3, 1 };
677   const UINT32 mask = masks[ (m_cur_Q  << 1) | m_new_Q ];
678
679   m_in_queue = 2; /* mark as taken ... */
680   m_cur_Q = m_new_Q;
681#if 0
682   core_terminal_t * t[256];
683   core_terminal_t *p = m_list_active.first();
684   int cnt = 0;
685   while (p != NULL)
686   {
687      if ((p->state() & mask) != 0)
688         t[cnt++] = p;
689      p = m_list_active.next(p);
690   }
691
692   for (int i=0; i<cnt; i++)
693      t[i]->netdev().update_dev();
694   core_terminal_t *p = m_list_active.first();
695
696   while (p != NULL)
697   {
698      p->update_dev(mask);
699      p = m_list_active.next(p);
700   }
701
702#else
703   core_terminal_t *p = m_list_active.first();
704
705   while (p != NULL)
706   {
707      p->update_dev(mask);
708      p = p->m_next;
709   }
710#endif
711}
712
713ATTR_COLD void net_t::reset()
714{
715   m_time = netlist_time::zero;
716   m_active = 0;
717   m_in_queue = 2;
718
719   m_new_Q = 0;
720   m_cur_Q = 0;
721   m_cur_Analog = 0.0;
722
723   /* rebuild m_list */
724
725   m_list_active.clear();
726   for (std::size_t i=0; i < m_core_terms.size(); i++)
727      m_list_active.add(*m_core_terms[i]);
728
729   for (std::size_t i=0; i < m_core_terms.size(); i++)
730      m_core_terms[i]->do_reset();
731
732   for (std::size_t i=0; i < m_core_terms.size(); i++)
733      if (m_core_terms[i]->state() != logic_t::STATE_INP_PASSIVE)
734         m_active++;
735}
736
737ATTR_COLD void net_t::register_con(core_terminal_t &terminal)
738{
739   terminal.set_net(*this);
740
741   m_core_terms.add(&terminal);
742
743   if (terminal.state() != logic_t::STATE_INP_PASSIVE)
744      m_active++;
745}
746
747ATTR_COLD void net_t::move_connections(net_t *dest_net)
748{
749   for (std::size_t i = 0; i < m_core_terms.size(); i++)
750   {
751      core_terminal_t *p = m_core_terms[i];
752      dest_net->register_con(*p);
753   }
754   m_core_terms.clear();
755   m_active = 0;
756}
757
758ATTR_COLD void net_t::merge_net(net_t *othernet)
759{
760   netlist().log().debug("merging nets ...\n");
761   if (othernet == NULL)
762      return; // Nothing to do
763
764   if (othernet == this)
765   {
766      netlist().log().warning("Connecting {1} to itself. This may be right, though\n", this->name());
767      return; // Nothing to do
768   }
769
770   if (this->isRailNet() && othernet->isRailNet())
771      netlist().log().fatal("Trying to merge two rail nets: {1} and {2}\n", this->name(), othernet->name());
772
773   if (othernet->isRailNet())
774   {
775      netlist().log().debug("othernet is railnet\n");
776      othernet->merge_net(this);
777   }
778   else
779   {
780      othernet->move_connections(this);
781   }
782}
783
784
785// ----------------------------------------------------------------------------------------
786// netlist_logic_net_t
787// ----------------------------------------------------------------------------------------
788
789ATTR_COLD logic_net_t::logic_net_t()
790   : net_t(LOGIC)
791{
792}
793
794
795ATTR_COLD void logic_net_t::reset()
796{
797   net_t::reset();
798}
799
800ATTR_COLD void logic_net_t::save_register()
801{
802   net_t::save_register();
803}
804
805// ----------------------------------------------------------------------------------------
806// netlist_analog_net_t
807// ----------------------------------------------------------------------------------------
808
809ATTR_COLD analog_net_t::analog_net_t()
810   : net_t(ANALOG)
811   , m_DD_n_m_1(0.0)
812   , m_h_n_m_1(1e-6)
813   , m_solver(NULL)
814{
815}
816
817ATTR_COLD void analog_net_t::reset()
818{
819   net_t::reset();
820}
821
822ATTR_COLD void analog_net_t::save_register()
823{
824   save(NLNAME(m_DD_n_m_1));
825   save(NLNAME(m_h_n_m_1));
826   net_t::save_register();
827}
828
829ATTR_COLD bool analog_net_t::already_processed(list_t *groups, int cur_group)
830{
831   if (isRailNet())
832      return true;
833   for (int i = 0; i <= cur_group; i++)
834   {
835      if (groups[i].contains(this))
836         return true;
837   }
838   return false;
839}
840
841ATTR_COLD void analog_net_t::process_net(list_t *groups, int &cur_group)
842{
843   if (num_cons() == 0)
844      return;
845   /* add the net */
846   groups[cur_group].add(this);
847   for (std::size_t i = 0; i < m_core_terms.size(); i++)
848   {
849      core_terminal_t *p = m_core_terms[i];
850      if (p->isType(terminal_t::TERMINAL))
851      {
852         terminal_t *pt = static_cast<terminal_t *>(p);
853         analog_net_t *other_net = &pt->m_otherterm->net().as_analog();
854         if (!other_net->already_processed(groups, cur_group))
855            other_net->process_net(groups, cur_group);
856      }
857   }
858}
859
860
861// ----------------------------------------------------------------------------------------
862// netlist_core_terminal_t
863// ----------------------------------------------------------------------------------------
864
865ATTR_COLD core_terminal_t::core_terminal_t(const type_t atype, const family_t afamily)
866: device_object_t(atype, afamily)
867, plinkedlist_element_t<core_terminal_t>()
868, m_net(NULL)
869, m_state(STATE_NONEX)
870{
871}
872
873ATTR_COLD void core_terminal_t::set_net(net_t &anet)
874{
875   m_net = &anet;
876}
877
878// ----------------------------------------------------------------------------------------
879// netlist_terminal_t
880// ----------------------------------------------------------------------------------------
881
882ATTR_COLD terminal_t::terminal_t()
883: core_terminal_t(TERMINAL, ANALOG)
884, m_Idr1(NULL)
885, m_go1(NULL)
886, m_gt1(NULL)
887, m_otherterm(NULL)
888{
889}
890
891ATTR_HOT void terminal_t::schedule_solve()
892{
893   // FIXME: Remove this after we found a way to remove *ALL* twoterms connected to railnets only.
894   if (net().as_analog().solver() != NULL)
895      net().as_analog().solver()->update_forced();
896}
897
898ATTR_HOT void terminal_t::schedule_after(const netlist_time &after)
899{
900   // FIXME: Remove this after we found a way to remove *ALL* twoterms connected to railnets only.
901   if (net().as_analog().solver() != NULL)
902      net().as_analog().solver()->update_after(after);
903}
904
905ATTR_COLD void terminal_t::reset()
906{
907   set_state(STATE_INP_ACTIVE);
908   set_ptr(m_Idr1, 0.0);
909   set_ptr(m_go1, netlist().gmin());
910   set_ptr(m_gt1, netlist().gmin());
911}
912
913ATTR_COLD void terminal_t::save_register()
914{
915   save(NLNAME(m_Idr1));
916   save(NLNAME(m_go1));
917   save(NLNAME(m_gt1));
918   core_terminal_t::save_register();
919}
920
921
922// ----------------------------------------------------------------------------------------
923// net_input_t
924// ----------------------------------------------------------------------------------------
925
926// ----------------------------------------------------------------------------------------
927// net_output_t
928// ----------------------------------------------------------------------------------------
929
930// ----------------------------------------------------------------------------------------
931// netlist_logic_output_t
932// ----------------------------------------------------------------------------------------
933
934ATTR_COLD logic_output_t::logic_output_t()
935   : logic_t(OUTPUT)
936{
937   set_state(STATE_OUT);
938   this->set_net(m_my_net);
939}
940
941ATTR_COLD void logic_output_t::init_object(core_device_t &dev, const pstring &aname)
942{
943   core_terminal_t::init_object(dev, aname);
944   net().init_object(dev.netlist(), aname + ".net");
945   net().register_railterminal(*this);
946}
947
948ATTR_COLD void logic_output_t::initial(const netlist_sig_t val)
949{
950   net().as_logic().initial(val);
951}
952
953
954// ----------------------------------------------------------------------------------------
955// netlist_analog_output_t
956// ----------------------------------------------------------------------------------------
957
958ATTR_COLD analog_output_t::analog_output_t()
959   : netlist_analog_t(OUTPUT), m_proxied_net(NULL)
960{
961   this->set_net(m_my_net);
962   set_state(STATE_OUT);
963
964   net().as_analog().m_cur_Analog = NL_FCONST(0.99);
965}
966
967ATTR_COLD void analog_output_t::init_object(core_device_t &dev, const pstring &aname)
968{
969   core_terminal_t::init_object(dev, aname);
970   net().init_object(dev.netlist(), aname + ".net");
971   net().register_railterminal(*this);
972}
973
974ATTR_COLD void analog_output_t::initial(const nl_double val)
975{
976   net().as_analog().m_cur_Analog = val;
977}
978
979// ----------------------------------------------------------------------------------------
980// netlist_param_t & friends
981// ----------------------------------------------------------------------------------------
982
983ATTR_COLD param_t::param_t(const param_type_t atype)
984   : device_object_t(PARAM, ANALOG)
985   , m_param_type(atype)
986{
987}
988
989ATTR_COLD const pstring param_model_t::model_type()
990{
991   if (m_map.size() == 0)
992      netlist().setup().model_parse(this->Value(), m_map);
993   return m_map["COREMODEL"];
994}
995
996
997ATTR_COLD const pstring param_model_t::model_value_str(const pstring &entity)
998{
999   if (m_map.size() == 0)
1000      netlist().setup().model_parse(this->Value(), m_map);
1001   return netlist().setup().model_value_str(m_map, entity);
1002}
1003
1004ATTR_COLD nl_double param_model_t::model_value(const pstring &entity)
1005{
1006   if (m_map.size() == 0)
1007      netlist().setup().model_parse(this->Value(), m_map);
1008   return netlist().setup().model_value(m_map, entity);
1009}
1010
1011} // namespace
1012
1013NETLIB_NAMESPACE_DEVICES_START()
1014
1015// ----------------------------------------------------------------------------------------
1016// mainclock
1017// ----------------------------------------------------------------------------------------
1018
1019ATTR_HOT /* inline */ void NETLIB_NAME(mainclock)::mc_update(logic_net_t &net)
1020{
1021   net.toggle_new_Q();
1022   net.update_devs();
1023}
1024
1025NETLIB_START(mainclock)
1026{
1027   register_output("Q", m_Q);
1028
1029   register_param("FREQ", m_freq, 7159000.0 * 5);
1030   m_inc = netlist_time::from_hz(m_freq.Value()*2);
1031}
1032
1033NETLIB_RESET(mainclock)
1034{
1035   m_Q.net().set_time(netlist_time::zero);
1036}
1037
1038NETLIB_UPDATE_PARAM(mainclock)
1039{
1040   m_inc = netlist_time::from_hz(m_freq.Value()*2);
1041}
1042
1043NETLIB_UPDATE(mainclock)
1044{
1045   logic_net_t &net = m_Q.net().as_logic();
1046   // this is only called during setup ...
1047   net.toggle_new_Q();
1048   net.set_time(netlist().time() + m_inc);
1049}
1050
1051NETLIB_NAMESPACE_DEVICES_END()
trunk/src/lib/netlist/nl_base.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nlbase.h
5 *
6 *  A mixed signal circuit simulation
7 *
8 *  D: Device
9 *  O: Rail output (output)
10 *  I: Infinite impedance input (input)
11 *  T: Terminal (finite impedance)
12 *
13 *  +---+     +---+     +---+     +---+     +---+
14 *  |   |     |   |     |   |     |   |     |   |
15 *  | D |     | D |     | D |     | D |     | D |
16 *  |   |     |   |     |   |     |   |     |   |
17 *  +-O-+     +-I-+     +-I-+     +-T-+     +-T-+
18 *    |         |         |         |         |
19 *  +-+---------+---------+---------+---------+-+
20 *  | rail net                                  |
21 *  +-------------------------------------------+
22 *
23 *  A rail net is a net which is driven by exactly one output with an
24 *  (idealized) internal resistance of zero.
25 *  Ideally, it can deliver infinite current.
26 *
27 *  A infinite resistance input does not source or sink current.
28 *
29 *  Terminals source or sink finite (but never zero) current.
30 *
31 *  The system differentiates between analog and logic input and outputs and
32 *  analog terminals. Analog and logic devices can not be connected to the
33 *  same net. Instead, proxy devices are inserted automatically:
34 *
35 *  +---+     +---+
36 *  |   |     |   |
37 *  | D1|     | D2|
38 *  | A |     | L |
39 *  +-O-+     +-I-+
40 *    |         |
41 *  +-+---------+---+
42 *  | rail net      |
43 *  +---------------+
44 *
45 *  is converted into
46 *              +----------+
47 *              |          |
48 *  +---+     +-+-+        |   +---+
49 *  |   |     | L |  A-L   |   |   |
50 *  | D1|     | D | Proxy  |   | D2|
51 *  | A |     | A |        |   |   |
52 *  +-O-+     +-I-+        |   +-I-+
53 *    |         |          |     |
54 *  +-+---------+--+     +-+-----+-------+
55 *  | rail net (A) |     | rail net (L)  |
56 *  +--------------|     +---------------+
57 *
58 *  This works both analog to logic as well as logic to analog.
59 *
60 *  The above is an advanced implementation of the existing discrete
61 *  subsystem in MAME. Instead of relying on a fixed time-step, analog devices
62 *  could either connect to fixed time-step clock or use an internal clock
63 *  to update them. This would however introduce macro devices for RC, diodes
64 *  and transistors again.
65 *
66 *  ============================================================================
67 *
68 *  Instead, the following approach in case of a pure terminal/input network
69 *  is taken:
70 *
71 *  +---+     +---+     +---+     +---+     +---+
72 *  |   |     |   |     |   |     |   |     |   |
73 *  | D |     | D |     | D |     | D |     | D |
74 *  |   |     |   |     |   |     |   |     |   |
75 *  +-T-+     +-I-+     +-I-+     +-T-+     +-T-+
76 *    |         |         |         |         |
77 *   '+'        |         |        '-'       '-'
78 *  +-+---------+---------+---------+---------+-+
79 *  | Calculated net                            |
80 *  +-------------------------------------------+
81 *
82 *  SPICE uses the following basic two terminal device:
83 *
84 *       (k)
85 *  +-----T-----+
86 *  |     |     |
87 *  |  +--+--+  |
88 *  |  |     |  |
89 *  |  R     |  |
90 *  |  R     |  |
91 *  |  R     I  |
92 *  |  |     I  |  Device n
93 *  |  V+    I  |
94 *  |  V     |  |
95 *  |  V-    |  |
96 *  |  |     |  |
97 *  |  +--+--+  |
98 *  |     |     |
99 *  +-----T-----+
100 *       (l)
101 *
102 *  This is a resistance in series to a voltage source and paralleled by a
103 *  current source. This is suitable to model voltage sources, current sources,
104 *  resistors, capacitors, inductances and diodes.
105 *
106 *  I(n,l) = - I(n,k) = ( V(k) - V - V(l) ) * (1/R(n)) + I(n)
107 *
108 *  Now, the sum of all currents for a given net must be 0:
109 *
110 *  Sum(n,I(n,l)) = 0 = sum(n, ( V(k) - V(n) - V(l) ) * (1/R(n)) + I(n) )
111 *
112 *  With G(n) = 1 / R(n) and sum(n, G(n)) = Gtot and k=k(n)
113 *
114 *  0 = - V(l) * Gtot + sum(n, (V(k(n)) - V(n)) * G(n) + I(n))
115 *
116 *  and with l=l(n) and fixed k
117 *
118 *  0 =  -V(k) * Gtot + sum(n, ( V(l(n) + V(n) ) * G(n) - I(n))
119 *
120 *  These equations represent a linear Matrix equation (with more math).
121 *
122 *  In the end the solution of the analog subsystem boils down to
123 *
124 *  (G - D) * V = I
125 *
126 *  with G being the conductance matrix, D a diagonal matrix with the total
127 *  conductance on the diagonal elements, V the net voltage vector and I the
128 *  current vector.
129 *
130 *  By using solely two terminal devices, we can simplify the whole calculation
131 *  significantly. A BJT now is a four terminal device with two terminals being
132 *  connected internally.
133 *
134 *  The system is solved using an iterative approach:
135 *
136 *  G * V - D * V = I
137 *
138 *  assuming V=Vn=Vo
139 *
140 *  Vn = D-1 * (I - G * Vo)
141 *
142 *  Each terminal thus has three properties:
143 *
144 *  a) Resistance
145 *  b) Voltage source
146 *  c) Current source/sink
147 *
148 *  Going forward, the approach can be extended e.g. to use a linear
149 *  equation solver.
150 *
151 *  The formal representation of the circuit will stay the same, thus scales.
152 *
153 */
154
155#ifndef NLBASE_H_
156#define NLBASE_H_
157
158#include "nl_lists.h"
159#include "nl_time.h"
160#include "nl_util.h"
161#include "plib/pstate.h"
162
163// ----------------------------------------------------------------------------------------
164// Type definitions
165// ----------------------------------------------------------------------------------------
166
167typedef UINT8 netlist_sig_t;
168
169//============================================================
170//  MACROS / netlist devices
171//============================================================
172
173#define NETLIB_NAMESPACE_DEVICES_START()    namespace netlist { namespace devices {
174#define NETLIB_NAMESPACE_DEVICES_END()  }}
175
176#define NETLIB_NAME(_chip) nld_ ## _chip
177
178#define NETLIB_NAME_STR_S(_s) # _s
179#define NETLIB_NAME_STR(_chip) NETLIB_NAME_STR_S(nld_ ## _chip)
180
181#define NETLIB_UPDATE(_chip) ATTR_HOT void NETLIB_NAME(_chip) :: update(void)
182#define NETLIB_START(_chip) ATTR_COLD void NETLIB_NAME(_chip) :: start(void)
183
184#define NETLIB_RESET(_chip) ATTR_COLD void NETLIB_NAME(_chip) :: reset(void)
185
186#define NETLIB_STOP(_chip) ATTR_COLD void NETLIB_NAME(_chip) :: stop(void)
187
188#define NETLIB_UPDATE_PARAM(_chip) ATTR_HOT void NETLIB_NAME(_chip) :: update_param(void)
189#define NETLIB_FUNC_VOID(_chip, _name, _params) ATTR_HOT void NETLIB_NAME(_chip) :: _name _params
190
191#define NETLIB_UPDATE_TERMINALS(_chip) ATTR_HOT void NETLIB_NAME(_chip) :: update_terminals(void)
192#define NETLIB_UPDATE_TERMINALSI() ATTR_HOT void update_terminals(void)
193#define NETLIB_UPDATEI() ATTR_HOT void update(void)
194
195#define NETLIB_DEVICE_BASE(_name, _pclass, _extra, _priv)                       \
196   class _name : public _pclass                                                \
197   {                                                                           \
198   public:                                                                     \
199      _name()                                                                 \
200      : _pclass()    { }                                                      \
201   protected:                                                                  \
202      _extra                                                                  \
203      ATTR_HOT void update();                                                 \
204      ATTR_HOT void start();                                                  \
205      ATTR_HOT void reset();                                                  \
206      _priv                                                                   \
207   }
208
209#define NETLIB_DEVICE_DERIVED_PURE(_name, _pclass)                            \
210      NETLIB_DEVICE_BASE(NETLIB_NAME(_name), NETLIB_NAME(_pclass), protected:, private:)
211
212#define NETLIB_DEVICE_DERIVED(_name, _pclass, _priv)                            \
213      NETLIB_DEVICE_BASE(NETLIB_NAME(_name), NETLIB_NAME(_pclass), protected:, _priv)
214
215#define NETLIB_DEVICE(_name, _priv)                                             \
216      NETLIB_DEVICE_BASE(NETLIB_NAME(_name), device_t, protected:, _priv)
217
218#define NETLIB_SUBDEVICE(_name, _priv)                                          \
219   class NETLIB_NAME(_name) : public device_t                                  \
220   {                                                                           \
221   public:                                                                     \
222      NETLIB_NAME(_name) ()                                                   \
223      : device_t()                                                            \
224         { }                                                                 \
225   /*protected:*/                                                              \
226      ATTR_HOT void update();                                                 \
227      ATTR_HOT void start();                                                  \
228      ATTR_HOT void reset();                                                  \
229   public:                                                                     \
230      _priv                                                                   \
231   }
232
233#define NETLIB_DEVICE_WITH_PARAMS(_name, _priv)                                 \
234      NETLIB_DEVICE_BASE(NETLIB_NAME(_name), device_t,                        \
235         ATTR_HOT void update_param();                                       \
236      , _priv)
237
238#define NETLIB_DEVICE_WITH_PARAMS_DERIVED(_name, _pclass, _priv)                \
239      NETLIB_DEVICE_BASE(NETLIB_NAME(_name), NETLIB_NAME(_pclass),            \
240         ATTR_HOT void update_param();                                       \
241      , _priv)
242
243#define NETLIB_LOGIC_FAMILY(_fam)                                               \
244virtual logic_family_desc_t *default_logic_family()                             \
245{                                                                               \
246   return netlist_family_ ## _fam;                                             \
247}
248
249
250//============================================================
251//  Asserts
252//============================================================
253
254#if defined(MAME_DEBUG)
255#define nl_assert(x)               do { if (1) if (!(x)) throw fatalerror_e(pfmt("assert: {1}:{2}: {3}")(__FILE__)(__LINE__)(#x) ); } while (0)
256#else
257#define nl_assert(x)               do { if (0) if (!(x)) throw fatalerror_e(pfmt("assert: {1}:{2}: {3}")(__FILE__)(__LINE__)(#x) ); } while (0)
258#endif
259#define nl_assert_always(x, msg)    do { if (!(x)) throw fatalerror_e(pfmt("Fatal error: {1}\nCaused by assert: {2}:{3}: {4}")(msg)(__FILE__)(__LINE__)(#x)); } while (0)
260
261
262// -----------------------------------------------------------------------------
263// forward definitions
264// -----------------------------------------------------------------------------
265
266//============================================================
267// Namespace starts
268//============================================================
269
270namespace netlist
271{
272   namespace devices
273   {
274      class matrix_solver_t;
275      class NETLIB_NAME(gnd);
276      class NETLIB_NAME(solver);
277      class NETLIB_NAME(mainclock);
278      class NETLIB_NAME(netlistparams);
279      class NETLIB_NAME(base_proxy);
280      class nld_base_d_to_a_proxy;
281   }
282
283   //============================================================
284   //  Exceptions
285   //============================================================
286
287   class fatalerror_e : public pexception
288   {
289   public:
290      fatalerror_e(const pstring &text) : pexception(text) { }
291      virtual ~fatalerror_e() throw() {}
292   };
293
294   class logic_output_t;
295   class analog_net_t;
296   class logic_net_t;
297   class net_t;
298   class setup_t;
299   class netlist_t;
300   class core_device_t;
301   class param_model_t;
302
303   // -----------------------------------------------------------------------------
304   // model_map_t
305   // -----------------------------------------------------------------------------
306
307   typedef phashmap_t<pstring, pstring> model_map_t;
308
309   // -----------------------------------------------------------------------------
310   // netlist_output_family_t
311   // -----------------------------------------------------------------------------
312
313   class logic_family_desc_t
314   {
315   public:
316      logic_family_desc_t() : m_is_static(false) {}
317      virtual ~logic_family_desc_t() {}
318      virtual devices::nld_base_d_to_a_proxy *create_d_a_proxy(logic_output_t *proxied) const = 0;
319
320      nl_double m_low_thresh_V;
321      nl_double m_high_thresh_V;
322      nl_double m_low_V;
323      nl_double m_high_V;
324      nl_double m_R_low;
325      nl_double m_R_high;
326
327      bool m_is_static;
328   };
329
330   class logic_family_t
331   {
332   public:
333
334      logic_family_t() : m_logic_family(NULL) {}
335      ~logic_family_t() { }
336
337      ATTR_HOT  logic_family_desc_t *logic_family() const { return m_logic_family; }
338      ATTR_COLD void set_logic_family(logic_family_desc_t *fam) { m_logic_family = fam; }
339
340   protected:
341      logic_family_desc_t *m_logic_family;
342   };
343
344   /* Terminals inherit the family description from the netlist_device
345    * The default is the ttl family, but any device can override the family.
346    * For individual terminals, these can be overwritten as well.
347    *
348    * Only devices of type GENERIC should have a family description entry
349    */
350
351
352   extern logic_family_desc_t *netlist_family_TTL;
353   extern logic_family_desc_t *netlist_family_CD4XXX;
354
355
356   // -----------------------------------------------------------------------------
357   // netlist_object_t
358   // -----------------------------------------------------------------------------
359
360   class object_t
361   {
362      P_PREVENT_COPYING(object_t)
363   public:
364      enum type_t {
365         TERMINAL = 0,
366         INPUT    = 1,
367         OUTPUT   = 2,
368         PARAM    = 3,
369         NET      = 4,
370         DEVICE   = 5,
371         NETLIST   = 6,
372         QUEUE   = 7
373      };
374      enum family_t {
375         // Terminal families
376         LOGIC,
377         ANALOG,
378         // Device families
379         GENERIC,    // <== devices usually fall into this category
380         TWOTERM,    // Generic twoterm ...
381         RESISTOR,   // Resistor
382         CAPACITOR,  // Capacitor
383         DIODE,      // Diode
384         DUMMY,      // DUMMY device without function
385         FRONTIER,   // Net frontier
386         BJT_EB,     // BJT(Ebers-Moll)
387         BJT_SWITCH, // BJT(Switch)
388         VCVS,       // Voltage controlled voltage source
389         VCCS,       // Voltage controlled current source
390         LVCCS,      // Voltage controlled current source (Current limited)
391         CCCS,       // Current controlled current source
392         VS,         // Voltage Source
393         CS,         // Current Source
394         GND         // GND device
395      };
396
397      ATTR_COLD object_t(const type_t atype, const family_t afamily);
398
399      virtual ~object_t();
400
401      ATTR_COLD void init_object(netlist_t &nl, const pstring &aname);
402      ATTR_COLD bool isInitialized() { return (m_netlist != NULL); }
403
404      ATTR_COLD const pstring &name() const;
405
406      PSTATE_INTERFACE_DECL()
407
408      ATTR_HOT  type_t type() const { return m_objtype; }
409      ATTR_HOT  family_t family() const { return m_family; }
410
411      ATTR_HOT  bool isType(const type_t atype) const { return (m_objtype == atype); }
412      ATTR_HOT  bool isFamily(const family_t afamily) const { return (m_family == afamily); }
413
414      ATTR_HOT  netlist_t & netlist() { return *m_netlist; }
415      ATTR_HOT  const netlist_t & netlist() const { return *m_netlist; }
416
417      ATTR_COLD void  do_reset()
418      {
419         reset();
420      }
421
422   protected:
423
424      virtual void reset() = 0;
425      // must call parent save_register !
426      virtual void save_register() { };
427
428   private:
429      pstring m_name;
430      const type_t m_objtype;
431      const family_t m_family;
432      netlist_t * m_netlist;
433   };
434
435   // -----------------------------------------------------------------------------
436   // netlist_owned_object_t
437   // -----------------------------------------------------------------------------
438
439   class device_object_t : public object_t
440   {
441      P_PREVENT_COPYING(device_object_t)
442   public:
443      ATTR_COLD device_object_t(const type_t atype, const family_t afamily);
444
445      ATTR_COLD void init_object(core_device_t &dev, const pstring &aname);
446
447      ATTR_HOT core_device_t &device() const { return *m_device; }
448   private:
449      core_device_t * m_device;
450   };
451
452
453   // -----------------------------------------------------------------------------
454   // netlist_core_terminal_t
455   // -----------------------------------------------------------------------------
456
457   class core_terminal_t : public device_object_t, public plinkedlist_element_t<core_terminal_t>
458   {
459      P_PREVENT_COPYING(core_terminal_t)
460   public:
461
462      typedef plist_t<core_terminal_t *> list_t;
463
464      /* needed here ... */
465
466      enum state_e {
467         STATE_INP_PASSIVE = 0,
468         STATE_INP_ACTIVE = 1,
469         STATE_INP_HL = 2,
470         STATE_INP_LH = 4,
471         STATE_OUT = 128,
472         STATE_NONEX = 256
473      };
474
475
476      ATTR_COLD core_terminal_t(const type_t atype, const family_t afamily);
477
478      //ATTR_COLD void init_object(netlist_core_device_t &dev, const pstring &aname);
479
480      ATTR_COLD void set_net(net_t &anet);
481      ATTR_COLD  void clear_net() { m_net = NULL; }
482      ATTR_HOT  bool has_net() const { return (m_net != NULL); }
483
484      ATTR_HOT  const net_t & net() const { return *m_net;}
485      ATTR_HOT  net_t & net() { return *m_net;}
486
487      ATTR_HOT  bool is_state(const state_e astate) const { return (m_state == astate); }
488      ATTR_HOT  state_e state() const { return m_state; }
489      ATTR_HOT  void set_state(const state_e astate)
490      {
491         nl_assert(astate != STATE_NONEX);
492         m_state = astate;
493      }
494
495
496      ATTR_HOT /* inline */ void update_dev(const UINT32 mask);
497
498   protected:
499      virtual void save_register()
500      {
501         save(NLNAME(m_state));
502         device_object_t::save_register();
503      }
504
505   private:
506      net_t *  m_net;
507      state_e m_state;
508   };
509
510   class terminal_t : public core_terminal_t
511   {
512      P_PREVENT_COPYING(terminal_t)
513   public:
514
515      typedef plist_t<terminal_t *> list_t;
516
517      ATTR_COLD terminal_t();
518
519      nl_double *m_Idr1; // drive current
520      nl_double *m_go1;  // conductance for Voltage from other term
521      nl_double *m_gt1;  // conductance for total conductance
522
523      ATTR_HOT  void set(const nl_double G)
524      {
525         set_ptr(m_Idr1, 0);
526         set_ptr(m_go1, G);
527         set_ptr(m_gt1, G);
528      }
529
530      ATTR_HOT  void set(const nl_double GO, const nl_double GT)
531      {
532         set_ptr(m_Idr1, 0);
533         set_ptr(m_go1, GO);
534         set_ptr(m_gt1, GT);
535      }
536
537      ATTR_HOT  void set(const nl_double GO, const nl_double GT, const nl_double I)
538      {
539         set_ptr(m_Idr1, I);
540         set_ptr(m_go1, GO);
541         set_ptr(m_gt1, GT);
542      }
543
544      ATTR_HOT void schedule_solve();
545      ATTR_HOT void schedule_after(const netlist_time &after);
546
547      terminal_t *m_otherterm;
548
549   protected:
550      virtual void save_register();
551
552      virtual void reset();
553   private:
554      ATTR_HOT  void set_ptr(nl_double *ptr, const nl_double val)
555      {
556         if (ptr != NULL && *ptr != val)
557         {
558            *ptr = val;
559         }
560      }
561   };
562
563
564   // -----------------------------------------------------------------------------
565   // netlist_input_t
566   // -----------------------------------------------------------------------------
567
568   class logic_t : public core_terminal_t, public logic_family_t
569   {
570   public:
571
572
573      ATTR_COLD logic_t(const type_t atype)
574         : core_terminal_t(atype, LOGIC), logic_family_t(),
575            m_proxy(NULL)
576      {
577      }
578
579      ATTR_COLD bool has_proxy() const { return (m_proxy != NULL); }
580      ATTR_COLD devices::nld_base_proxy *get_proxy() const  { return m_proxy; }
581      ATTR_COLD void set_proxy(devices::nld_base_proxy *proxy) { m_proxy = proxy; }
582
583   protected:
584
585   private:
586      devices::nld_base_proxy *m_proxy;
587   };
588
589   class netlist_analog_t : public core_terminal_t
590   {
591   public:
592
593
594      ATTR_COLD netlist_analog_t(const type_t atype)
595         : core_terminal_t(atype, ANALOG)
596      {
597      }
598
599   protected:
600
601   private:
602   };
603
604   // -----------------------------------------------------------------------------
605   // netlist_logic_input_t
606   // -----------------------------------------------------------------------------
607
608   class logic_input_t : public logic_t
609   {
610   public:
611      ATTR_COLD logic_input_t()
612         : logic_t(INPUT)
613      {
614         set_state(STATE_INP_ACTIVE);
615      }
616
617      ATTR_HOT  netlist_sig_t Q() const;
618      ATTR_HOT  netlist_sig_t last_Q() const;
619
620      ATTR_HOT  void inactivate();
621      ATTR_HOT  void activate();
622      ATTR_HOT  void activate_hl();
623      ATTR_HOT  void activate_lh();
624
625   protected:
626      virtual void reset()
627      {
628         //netlist_core_terminal_t::reset();
629         set_state(STATE_INP_ACTIVE);
630      }
631
632   };
633
634   // -----------------------------------------------------------------------------
635   // netlist_analog_input_t
636   // -----------------------------------------------------------------------------
637
638   class analog_input_t : public netlist_analog_t
639   {
640   public:
641      ATTR_COLD analog_input_t()
642         : netlist_analog_t(INPUT)
643      {
644         set_state(STATE_INP_ACTIVE);
645      }
646
647      ATTR_HOT  nl_double Q_Analog() const;
648
649   protected:
650      virtual void reset()
651      {
652         //netlist_core_terminal_t::reset();
653         set_state(STATE_INP_ACTIVE);
654      }
655   };
656
657   // -----------------------------------------------------------------------------
658   // net_net_t
659   // -----------------------------------------------------------------------------
660
661   class net_t : public object_t
662   {
663      P_PREVENT_COPYING(net_t)
664   public:
665
666      typedef plist_t<net_t *> list_t;
667
668      ATTR_COLD net_t(const family_t afamily);
669      virtual ~net_t();
670
671      ATTR_COLD void init_object(netlist_t &nl, const pstring &aname);
672
673      ATTR_COLD void register_con(core_terminal_t &terminal);
674      ATTR_COLD void merge_net(net_t *othernet);
675      ATTR_COLD void register_railterminal(core_terminal_t &mr);
676
677      ATTR_HOT  logic_net_t & as_logic();
678      ATTR_HOT  const logic_net_t &  as_logic() const;
679
680      ATTR_HOT  analog_net_t & as_analog();
681      ATTR_HOT  const analog_net_t & as_analog() const;
682
683      ATTR_HOT void update_devs();
684
685      ATTR_HOT  const netlist_time &time() const { return m_time; }
686      ATTR_HOT  void set_time(const netlist_time &ntime) { m_time = ntime; }
687
688      ATTR_HOT  bool isRailNet() const { return !(m_railterminal == NULL); }
689      ATTR_HOT  core_terminal_t & railterminal() const { return *m_railterminal; }
690
691      ATTR_HOT  void push_to_queue(const netlist_time &delay);
692      ATTR_HOT  void reschedule_in_queue(const netlist_time &delay);
693      ATTR_HOT bool  is_queued() const { return m_in_queue == 1; }
694
695      ATTR_HOT  int num_cons() const { return m_core_terms.size(); }
696
697      ATTR_HOT void inc_active(core_terminal_t &term);
698      ATTR_HOT void dec_active(core_terminal_t &term);
699
700      ATTR_COLD void rebuild_list();     /* rebuild m_list after a load */
701
702      ATTR_COLD void move_connections(net_t *new_net);
703
704      plist_t<core_terminal_t *> m_core_terms; // save post-start m_list ...
705
706      ATTR_HOT  void set_Q_time(const netlist_sig_t &newQ, const netlist_time &at)
707      {
708         if (newQ != m_new_Q)
709         {
710            m_in_queue = 0;
711            m_time = at;
712         }
713         m_cur_Q = m_new_Q = newQ;
714      }
715
716   protected:  //FIXME: needed by current solver code
717
718      virtual void save_register();
719      virtual void reset();
720
721      netlist_sig_t m_new_Q;
722      netlist_sig_t m_cur_Q;
723
724   private:
725
726      core_terminal_t * m_railterminal;
727      plinkedlist_t<core_terminal_t> m_list_active;
728
729      netlist_time m_time;
730      INT32        m_active;
731      UINT8        m_in_queue;    /* 0: not in queue, 1: in queue, 2: last was taken */
732
733   public:
734      // We have to have those on one object. Dividing those does lead
735      // to a significant performance hit
736      // FIXME: Have to fix the public at some time
737      nl_double m_cur_Analog;
738
739   };
740
741   class logic_net_t : public net_t
742   {
743      P_PREVENT_COPYING(logic_net_t)
744   public:
745
746      typedef plist_t<logic_net_t *> list_t;
747
748      ATTR_COLD logic_net_t();
749      virtual ~logic_net_t() { };
750
751      ATTR_HOT  netlist_sig_t Q() const
752      {
753         return m_cur_Q;
754      }
755
756      ATTR_HOT  netlist_sig_t new_Q() const
757      {
758         return m_new_Q;
759      }
760
761      ATTR_HOT  void set_Q(const netlist_sig_t &newQ, const netlist_time &delay)
762      {
763         if (newQ !=  m_new_Q)
764         {
765            m_new_Q = newQ;
766            push_to_queue(delay);
767         }
768      }
769
770      ATTR_HOT  void toggle_new_Q()
771      {
772         m_new_Q ^= 1;
773      }
774
775      ATTR_COLD void initial(const netlist_sig_t val)
776      {
777         m_cur_Q = val;
778         m_new_Q = val;
779      }
780
781      /* internal state support
782       * FIXME: get rid of this and implement export/import in MAME
783       */
784      ATTR_COLD  netlist_sig_t &Q_state_ptr()
785      {
786         return m_cur_Q;
787      }
788
789   protected:  //FIXME: needed by current solver code
790
791      virtual void save_register();
792      virtual void reset();
793
794
795   private:
796
797   public:
798
799   };
800
801   class analog_net_t : public net_t
802   {
803      P_PREVENT_COPYING(analog_net_t)
804   public:
805
806      typedef plist_t<analog_net_t *> list_t;
807
808      ATTR_COLD analog_net_t();
809      virtual ~analog_net_t() { };
810
811      ATTR_HOT  nl_double Q_Analog() const
812      {
813         return m_cur_Analog;
814      }
815
816      ATTR_COLD  nl_double &Q_Analog_state_ptr()
817      {
818         return m_cur_Analog;
819      }
820
821      ATTR_HOT devices::matrix_solver_t *solver() { return m_solver; }
822
823      ATTR_COLD bool already_processed(list_t *groups, int cur_group);
824      ATTR_COLD void process_net(list_t *groups, int &cur_group);
825
826   protected:
827
828      virtual void save_register();
829      virtual void reset();
830
831
832   private:
833
834   public:
835      nl_double m_DD_n_m_1;
836      nl_double m_h_n_m_1;
837
838      //FIXME: needed by current solver code
839      devices::matrix_solver_t *m_solver;
840   };
841
842   // -----------------------------------------------------------------------------
843   // net_output_t
844   // -----------------------------------------------------------------------------
845
846   class logic_output_t : public logic_t
847   {
848      P_PREVENT_COPYING(logic_output_t)
849   public:
850
851      ATTR_COLD logic_output_t();
852
853      ATTR_COLD void init_object(core_device_t &dev, const pstring &aname);
854      virtual void reset()
855      {
856         set_state(STATE_OUT);
857      }
858
859      ATTR_COLD void initial(const netlist_sig_t val);
860
861      ATTR_HOT  void set_Q(const netlist_sig_t newQ, const netlist_time &delay)
862      {
863         net().as_logic().set_Q(newQ, delay);
864      }
865
866   private:
867      logic_net_t m_my_net;
868   };
869
870   class analog_output_t : public netlist_analog_t
871   {
872      P_PREVENT_COPYING(analog_output_t)
873   public:
874
875      ATTR_COLD analog_output_t();
876
877      ATTR_COLD void init_object(core_device_t &dev, const pstring &aname);
878      virtual void reset()
879      {
880         set_state(STATE_OUT);
881      }
882
883      ATTR_COLD void initial(const nl_double val);
884
885      ATTR_HOT  void set_Q(const nl_double newQ);
886
887      analog_net_t *m_proxied_net; // only for proxy nets in analog input logic
888
889   private:
890      analog_net_t m_my_net;
891   };
892
893   // -----------------------------------------------------------------------------
894   // net_param_t
895   // -----------------------------------------------------------------------------
896
897   class param_t : public device_object_t
898   {
899      P_PREVENT_COPYING(param_t)
900   public:
901
902      enum param_type_t {
903         MODEL,
904         STRING,
905         DOUBLE,
906         INTEGER,
907         LOGIC
908      };
909
910      ATTR_COLD param_t(const param_type_t atype);
911
912      ATTR_HOT  param_type_t param_type() const { return m_param_type; }
913
914   protected:
915
916      virtual void reset() { }
917
918   private:
919      const param_type_t m_param_type;
920   };
921
922   template <class C, param_t::param_type_t T>
923   class param_template_t : public param_t
924   {
925      P_PREVENT_COPYING(param_template_t)
926   public:
927      ATTR_COLD param_template_t()
928      : param_t(T)
929      , m_param(C(0))
930      {
931      }
932
933      operator const C() const { return Value(); }
934
935      ATTR_HOT  void setTo(const C &param);
936      ATTR_COLD  void initial(const C &val) { m_param = val; }
937      ATTR_HOT  C Value() const { return m_param;   }
938
939   protected:
940      virtual void save_register()
941      {
942         /* pstrings not yet supported, these need special logic */
943         if (T != param_t::STRING && T != param_t::MODEL)
944            save(NLNAME(m_param));
945         param_t::save_register();
946      }
947
948      virtual void changed() { }
949      C m_param;
950   private:
951   };
952
953   typedef param_template_t<nl_double, param_t::DOUBLE> param_double_t;
954   typedef param_template_t<int, param_t::INTEGER> param_int_t;
955   typedef param_template_t<pstring, param_t::STRING> param_str_t;
956
957   class param_logic_t : public param_int_t
958   {
959      P_PREVENT_COPYING(param_logic_t)
960   public:
961      ATTR_COLD param_logic_t() : param_int_t() { };
962   };
963
964   class param_model_t : public param_template_t<pstring, param_t::MODEL>
965   {
966      P_PREVENT_COPYING(param_model_t)
967   public:
968      ATTR_COLD param_model_t() : param_template_t<pstring, param_t::MODEL>() { }
969
970      /* these should be cached! */
971      ATTR_COLD nl_double model_value(const pstring &entity);
972      ATTR_COLD const pstring model_value_str(const pstring &entity);
973      ATTR_COLD const pstring model_type();
974   protected:
975      void changed()
976      {
977         m_map.clear();
978      }
979   private:
980      model_map_t m_map;
981   };
982
983   // -----------------------------------------------------------------------------
984   // core_device_t
985   // -----------------------------------------------------------------------------
986
987   class core_device_t : public object_t, public logic_family_t
988   {
989      P_PREVENT_COPYING(core_device_t)
990   public:
991
992      typedef plist_t<core_device_t *> list_t;
993
994      ATTR_COLD core_device_t(const family_t afamily);
995
996      virtual ~core_device_t();
997
998      virtual void init(netlist_t &anetlist, const pstring &name);
999      ATTR_HOT virtual void update_param() {}
1000
1001      ATTR_HOT  void update_dev()
1002      {
1003         begin_timing(stat_total_time);
1004         inc_stat(stat_update_count);
1005
1006   #if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF)
1007         (this->*m_static_update)();
1008   #elif ((NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV) || (NL_PMF_TYPE == NL_PMF_TYPE_INTERNAL))
1009         m_static_update(this);
1010   #else
1011         update();
1012   #endif
1013         end_timing(stat_total_time);
1014      }
1015      ATTR_COLD void start_dev();
1016      ATTR_COLD void stop_dev();
1017
1018      ATTR_HOT netlist_sig_t INPLOGIC_PASSIVE(logic_input_t &inp);
1019
1020      ATTR_HOT  netlist_sig_t INPLOGIC(const logic_input_t &inp) const
1021      {
1022         nl_assert(inp.state() != logic_t::STATE_INP_PASSIVE);
1023         return inp.Q();
1024      }
1025
1026      ATTR_HOT  void OUTLOGIC(logic_output_t &out, const netlist_sig_t val, const netlist_time &delay)
1027      {
1028         out.set_Q(val, delay);
1029      }
1030
1031      ATTR_HOT  nl_double INPANALOG(const analog_input_t &inp) const { return inp.Q_Analog(); }
1032
1033      ATTR_HOT  nl_double TERMANALOG(const terminal_t &term) const { return term.net().as_analog().Q_Analog(); }
1034
1035      ATTR_HOT  void OUTANALOG(analog_output_t &out, const nl_double val)
1036      {
1037         out.set_Q(val);
1038      }
1039
1040      ATTR_HOT virtual void inc_active() {  }
1041
1042      ATTR_HOT virtual void dec_active() {  }
1043
1044      ATTR_HOT virtual void step_time(ATTR_UNUSED const nl_double st) { }
1045      ATTR_HOT virtual void update_terminals() { }
1046
1047   #if (NL_KEEP_STATISTICS)
1048      /* stats */
1049      osd_ticks_t stat_total_time;
1050      INT32 stat_update_count;
1051      INT32 stat_call_count;
1052   #endif
1053
1054   protected:
1055
1056      ATTR_HOT virtual void update() { }
1057      virtual void start() { }
1058      virtual void stop() { }                                                  \
1059      virtual logic_family_desc_t *default_logic_family()
1060      {
1061         return netlist_family_TTL;
1062      }
1063
1064   private:
1065
1066      #if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF)
1067      typedef void (core_device_t::*net_update_delegate)();
1068      #elif ((NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV) || (NL_PMF_TYPE == NL_PMF_TYPE_INTERNAL))
1069      typedef MEMBER_ABI void (*net_update_delegate)(core_device_t *);
1070      #endif
1071
1072   #if (NL_PMF_TYPE > NL_PMF_TYPE_VIRTUAL)
1073      net_update_delegate m_static_update;
1074   #endif
1075   };
1076
1077   // -----------------------------------------------------------------------------
1078   // device_t
1079   // -----------------------------------------------------------------------------
1080
1081   class device_t : public core_device_t
1082   {
1083      P_PREVENT_COPYING(device_t)
1084   public:
1085
1086      ATTR_COLD device_t();
1087      ATTR_COLD device_t(const family_t afamily);
1088
1089      virtual ~device_t();
1090
1091      virtual void init(netlist_t &anetlist, const pstring &name);
1092
1093      ATTR_COLD setup_t &setup();
1094
1095      ATTR_COLD void register_sub(const pstring &name, device_t &dev);
1096      ATTR_COLD void register_subalias(const pstring &name, core_terminal_t &term);
1097      ATTR_COLD void register_subalias(const pstring &name, const pstring &aliased);
1098      ATTR_COLD void register_terminal(const pstring &name, terminal_t &port);
1099      ATTR_COLD void register_output(const pstring &name, analog_output_t &out);
1100      ATTR_COLD void register_output(const pstring &name, logic_output_t &out);
1101      ATTR_COLD void register_input(const pstring &name, analog_input_t &in);
1102      ATTR_COLD void register_input(const pstring &name, logic_input_t &in);
1103
1104      ATTR_COLD void connect_late(const pstring &t1, const pstring &t2);
1105      ATTR_COLD void connect_late(core_terminal_t &t1, core_terminal_t &t2);
1106      ATTR_COLD void connect_direct(core_terminal_t &t1, core_terminal_t &t2);
1107
1108      plist_t<pstring> m_terminals;
1109
1110   protected:
1111
1112      ATTR_HOT virtual void update() { }
1113      ATTR_HOT virtual void start() { }
1114      ATTR_HOT virtual void update_terminals() { }
1115
1116      template <class C, class T>
1117      ATTR_COLD void register_param(const pstring &sname, C &param, const T initialVal);
1118
1119   private:
1120   };
1121
1122
1123   // -----------------------------------------------------------------------------
1124   // netlist_queue_t
1125   // -----------------------------------------------------------------------------
1126
1127   class queue_t : public timed_queue<net_t *, netlist_time>,
1128                     public object_t,
1129                     public pstate_callback_t
1130   {
1131   public:
1132      queue_t(netlist_t &nl);
1133
1134   protected:
1135
1136      void reset() {}
1137
1138      void register_state(pstate_manager_t &manager, const pstring &module);
1139      void on_pre_save();
1140      void on_post_load();
1141
1142   private:
1143      struct names_t { char m_buf[64]; };
1144      int m_qsize;
1145      parray_t<netlist_time::INTERNALTYPE> m_times;
1146      parray_t<names_t> m_names;
1147   };
1148
1149   // -----------------------------------------------------------------------------
1150   // netlist_base_t
1151   // -----------------------------------------------------------------------------
1152
1153
1154   class netlist_t : public object_t, public pstate_manager_t, public plog_dispatch_intf
1155   {
1156      P_PREVENT_COPYING(netlist_t)
1157   public:
1158
1159      netlist_t();
1160      virtual ~netlist_t();
1161
1162      ATTR_COLD void start();
1163      ATTR_COLD void stop();
1164
1165      ATTR_HOT  const queue_t &queue() const { return m_queue; }
1166      ATTR_HOT  queue_t &queue() { return m_queue; }
1167      ATTR_HOT  const netlist_time &time() const { return m_time; }
1168      ATTR_HOT  devices::NETLIB_NAME(solver) *solver() const { return m_solver; }
1169      ATTR_HOT  devices::NETLIB_NAME(gnd) *gnd() const { return m_gnd; }
1170      ATTR_HOT nl_double gmin() const;
1171
1172      ATTR_HOT void push_to_queue(net_t &out, const netlist_time &attime);
1173      ATTR_HOT void remove_from_queue(net_t &out);
1174
1175      ATTR_HOT void process_queue(const netlist_time &delta);
1176      ATTR_HOT  void abort_current_queue_slice() { m_stop = netlist_time::zero; }
1177
1178      ATTR_HOT  const bool &use_deactivate() const { return m_use_deactivate; }
1179
1180      ATTR_COLD void rebuild_lists(); /* must be called after post_load ! */
1181
1182      ATTR_COLD void set_setup(setup_t *asetup) { m_setup = asetup;  }
1183      ATTR_COLD setup_t &setup() { return *m_setup; }
1184
1185      ATTR_COLD net_t *find_net(const pstring &name);
1186
1187      template<class _C>
1188      ATTR_COLD plist_t<_C *> get_device_list()
1189      {
1190         plist_t<_C *> tmp;
1191         for (std::size_t i = 0; i < m_devices.size(); i++)
1192         {
1193            _C *dev = dynamic_cast<_C *>(m_devices[i]);
1194            if (dev != NULL)
1195               tmp.add(dev);
1196         }
1197         return tmp;
1198      }
1199
1200      template<class _C>
1201      ATTR_COLD _C *get_first_device()
1202      {
1203         for (std::size_t i = 0; i < m_devices.size(); i++)
1204         {
1205            _C *dev = dynamic_cast<_C *>(m_devices[i]);
1206            if (dev != NULL)
1207               return dev;
1208         }
1209         return NULL;
1210      }
1211
1212      template<class _C>
1213      ATTR_COLD _C *get_single_device(const char *classname)
1214      {
1215         _C *ret = NULL;
1216         for (std::size_t i = 0; i < m_devices.size(); i++)
1217         {
1218            _C *dev = dynamic_cast<_C *>(m_devices[i]);
1219            if (dev != NULL)
1220            {
1221               if (ret != NULL)
1222                  this->log().fatal("more than one {1} device found", classname);
1223               else
1224                  ret = dev;
1225            }
1226         }
1227         return ret;
1228      }
1229
1230      pnamedlist_t<device_t *> m_devices;
1231      net_t::list_t m_nets;
1232   #if (NL_KEEP_STATISTICS)
1233      pnamedlist_t<core_device_t *> m_started_devices;
1234   #endif
1235
1236   ATTR_COLD plog_base<NL_DEBUG> &log() { return m_log; }
1237   ATTR_COLD const plog_base<NL_DEBUG> &log() const { return m_log; }
1238
1239   protected:
1240
1241      // any derived netlist must override vlog inherited from plog_base
1242      //  virtual void vlog(const plog_level &l, const pstring &ls) = 0;
1243
1244      /* from netlist_object */
1245      virtual void reset();
1246      virtual void save_register();
1247
1248   #if (NL_KEEP_STATISTICS)
1249      // performance
1250      int m_perf_out_processed;
1251      int m_perf_inp_processed;
1252      int m_perf_inp_active;
1253   #endif
1254
1255   private:
1256      netlist_time                m_stop;     // target time for current queue processing
1257
1258      netlist_time                m_time;
1259      bool                        m_use_deactivate;
1260      queue_t                     m_queue;
1261
1262
1263      devices::NETLIB_NAME(mainclock) *    m_mainclock;
1264      devices::NETLIB_NAME(solver) *       m_solver;
1265      devices::NETLIB_NAME(gnd) *          m_gnd;
1266
1267
1268      devices::NETLIB_NAME(netlistparams) *m_params;
1269      setup_t *m_setup;
1270      plog_base<NL_DEBUG> m_log;
1271   };
1272
1273   // -----------------------------------------------------------------------------
1274   // inline implementations
1275   // -----------------------------------------------------------------------------
1276
1277   PSTATE_INTERFACE(object_t, m_netlist, name())
1278
1279   template <class C, param_t::param_type_t T>
1280   ATTR_HOT inline void param_template_t<C, T>::setTo(const C &param)
1281   {
1282      if (m_param != param)
1283      {
1284         m_param = param;
1285         changed();
1286         device().update_param();
1287      }
1288   }
1289
1290   ATTR_HOT inline logic_net_t & net_t::as_logic()
1291   {
1292      nl_assert(family() == LOGIC);
1293      return static_cast<logic_net_t &>(*this);
1294   }
1295
1296   ATTR_HOT inline const logic_net_t & net_t::as_logic() const
1297   {
1298      nl_assert(family() == LOGIC);
1299      return static_cast<const logic_net_t &>(*this);
1300   }
1301
1302   ATTR_HOT inline analog_net_t & net_t::as_analog()
1303   {
1304      nl_assert(family() == ANALOG);
1305      return static_cast<analog_net_t &>(*this);
1306   }
1307
1308   ATTR_HOT inline const analog_net_t & net_t::as_analog() const
1309   {
1310      nl_assert(family() == ANALOG);
1311      return static_cast<const analog_net_t &>(*this);
1312   }
1313
1314
1315   ATTR_HOT inline void logic_input_t::inactivate()
1316   {
1317      if (EXPECTED(!is_state(STATE_INP_PASSIVE)))
1318      {
1319         set_state(STATE_INP_PASSIVE);
1320         net().as_logic().dec_active(*this);
1321      }
1322   }
1323
1324   ATTR_HOT inline void logic_input_t::activate()
1325   {
1326      if (is_state(STATE_INP_PASSIVE))
1327      {
1328         net().as_logic().inc_active(*this);
1329         set_state(STATE_INP_ACTIVE);
1330      }
1331   }
1332
1333   ATTR_HOT inline void logic_input_t::activate_hl()
1334   {
1335      if (is_state(STATE_INP_PASSIVE))
1336      {
1337         net().as_logic().inc_active(*this);
1338         set_state(STATE_INP_HL);
1339      }
1340   }
1341
1342   ATTR_HOT inline void logic_input_t::activate_lh()
1343   {
1344      if (is_state(STATE_INP_PASSIVE))
1345      {
1346         net().as_logic().inc_active(*this);
1347         set_state(STATE_INP_LH);
1348      }
1349   }
1350
1351
1352   ATTR_HOT inline void net_t::push_to_queue(const netlist_time &delay)
1353   {
1354      if (!is_queued() && (num_cons() > 0))
1355      {
1356         m_time = netlist().time() + delay;
1357         m_in_queue = (m_active > 0);     /* queued ? */
1358         if (m_in_queue)
1359         {
1360            netlist().push_to_queue(*this, m_time);
1361         }
1362      }
1363   }
1364
1365   ATTR_HOT inline void net_t::reschedule_in_queue(const netlist_time &delay)
1366   {
1367      if (is_queued())
1368         netlist().remove_from_queue(*this);
1369
1370      m_time = netlist().time() + delay;
1371      m_in_queue = (m_active > 0);     /* queued ? */
1372      if (EXPECTED(m_in_queue))
1373      {
1374         netlist().push_to_queue(*this, m_time);
1375      }
1376   }
1377
1378
1379   ATTR_HOT inline netlist_sig_t logic_input_t::Q() const
1380   {
1381      return net().as_logic().Q();
1382   }
1383
1384   ATTR_HOT inline nl_double analog_input_t::Q_Analog() const
1385   {
1386      return net().as_analog().Q_Analog();
1387   }
1388
1389   ATTR_HOT inline void analog_output_t::set_Q(const nl_double newQ)
1390   {
1391      if (newQ != net().as_analog().m_cur_Analog)
1392      {
1393         net().as_analog().m_cur_Analog = newQ;
1394         net().push_to_queue(NLTIME_FROM_NS(1));
1395      }
1396   }
1397
1398   ATTR_HOT inline void netlist_t::push_to_queue(net_t &out, const netlist_time &attime)
1399   {
1400      m_queue.push(queue_t::entry_t(attime, &out));
1401   }
1402
1403   ATTR_HOT inline void netlist_t::remove_from_queue(net_t &out)
1404   {
1405      m_queue.remove(&out);
1406   }
1407
1408}
1409
1410NETLIST_SAVE_TYPE(netlist::core_terminal_t::state_e, DT_INT);
1411
1412
1413#endif /* NLBASE_H_ */
trunk/src/lib/netlist/nl_config.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nlconfig.h
5 *
6 */
7
8#ifndef NLCONFIG_H_
9#define NLCONFIG_H_
10
11#include "plib/pconfig.h"
12
13//============================================================
14//  SETUP
15//============================================================
16
17/*
18 * The following options determine how object::update is called.
19 * NL_PMF_TYPE_VIRTUAL
20 *      Use stock virtual call
21 *
22 * NL_PMF_TYPE_GNUC_PMF
23 *      Use standard pointer to member function syntax
24 *
25 *  NL_PMF_TYPE_GNUC_PMF_CONV
26 *      Use gnu extension and convert the pmf to a function pointer.
27 *      This is not standard compliant and needs
28 *      -Wno-pmf-conversions to compile.
29 *
30 *  NL_PMF_TYPE_INTERNAL
31 *      Use the same approach as MAME for deriving the function pointer.
32 *      This is compiler-dependant as well
33 *
34 *  Benchmarks for ./nltool -c run -f src/mame/drivers/nl_pong.c -t 10 -n pong_fast
35 *
36 *  NL_PMF_TYPE_INTERNAL:       215%
37 *  NL_PMF_TYPE_GNUC_PMF:       163%
38 *  NL_PMF_TYPE_GNUC_PMF_CONV:  215%
39 *  NL_PMF_TYPE_VIRTUAL:        213%
40 *
41 *  The whole exercise was done to avoid virtual calls. In prior versions of
42 *  netlist, the INTERNAL and GNUC_PMF_CONV approach provided significant improvement.
43 *  Since than, ATTR_COLD was removed from functions declared as virtual.
44 *  This may explain that the recent benchmarks show no difference at all.
45 *
46 *  Disappointing is the GNUC_PMF performance.
47 */
48
49// This will be autodetected
50// #define NL_PMF_TYPE 2
51
52#define NL_PMF_TYPE_VIRTUAL         0
53#define NL_PMF_TYPE_GNUC_PMF        1
54#define NL_PMF_TYPE_GNUC_PMF_CONV   2
55#define NL_PMF_TYPE_INTERNAL        3
56
57#ifndef NL_PMF_TYPE
58   #if PHAS_PMF_INTERNAL
59      #define NL_PMF_TYPE NL_PMF_TYPE_INTERNAL
60   #else
61      #define NL_PMF_TYPE NL_PMF_TYPE_VIRTUAL
62   #endif
63#endif
64
65#if (NL_PMF_TYPE == NL_PMF_TYPE_GNUC_PMF_CONV)
66#pragma GCC diagnostic ignored "-Wpmf-conversions"
67#endif
68
69#define USE_TRUTHTABLE          (1)
70
71// The following adds about 10% performance ...
72
73#if !defined(USE_OPENMP)
74#define USE_OPENMP              (0)
75#endif // !defined(USE_OPENMP)
76
77// Use nano-second resolution - Sufficient for now
78#define NETLIST_INTERNAL_RES        (U64(1000000000))
79//#define NETLIST_INTERNAL_RES      (U64(1000000000000))
80
81#define NETLIST_CLOCK               (NETLIST_INTERNAL_RES)
82
83#define NETLIST_GMIN_DEFAULT    (1e-9)
84
85//#define nl_double float
86//#define NL_FCONST(x) (x ## f)
87
88#define nl_double double
89#define NL_FCONST(x) x
90
91
92//============================================================
93//  Solver defines
94//============================================================
95
96#define USE_MATRIX_GS (0)
97#define USE_GABS (1)
98// savings are eaten up by effort
99// FIXME: Convert into solver parameter
100#define USE_LINEAR_PREDICTION (0)
101
102
103//============================================================
104//  DEBUGGING
105//============================================================
106
107#define NL_DEBUG                    (false)
108#define NL_KEEP_STATISTICS          (0)
109
110//============================================================
111//  General Macros
112//============================================================
113
114#if defined(_OPENMP)
115#define HAS_OPENMP ( _OPENMP >= 200805 )
116#else
117#define HAS_OPENMP (0)
118#endif
119
120//============================================================
121//  Performance tracking
122//============================================================
123
124#if NL_KEEP_STATISTICS
125#include "eminline.h"
126#define add_to_stat(v,x)        do { v += (x); } while (0)
127#define inc_stat(v)             add_to_stat(v, 1)
128#define begin_timing(v)         do { v -= get_profile_ticks(); } while (0)
129#define end_timing(v)           do { v += get_profile_ticks(); } while (0)
130#else
131#define add_to_stat(v,x)        do { } while (0)
132#define inc_stat(v)             add_to_stat(v, 1)
133#define begin_timing(v)         do { } while (0)
134#define end_timing(v)           do { } while (0)
135#endif
136
137// this macro passes an item followed by a string version of itself as two consecutive parameters
138#define NLNAME(x) x, #x
139
140//============================================================
141//  WARNINGS
142//============================================================
143
144#if (USE_OPENMP)
145#if (!(HAS_OPENMP))
146#error To use openmp compile and link with "-fopenmp"
147#endif
148#endif
149
150
151#endif /* NLCONFIG_H_ */
trunk/src/lib/netlist/nl_dice_compat.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nl_dice_compat.h
5 *
6 * The follwoing script will convert a circuit using dice syntax into netlist
7 * syntax. It's not fail proof, but eases the manual work involved significantly.
8
9sed -e 's/#define \(.*\)"\(.*\)"[ \t]*,[ \t]*\(.*\)/NET_ALIAS(\1,\2.\3)/' src/mame/drivers/nl_breakout.c   \
10| sed -e 's/^[ \t]*$/NL_EMPTY /' \
11| cpp -I src/emu -I src/osd/ -DNL_CONVERT_CPP -P -CC - \
12| sed -e 's/\(TTL_.*\)("\(.*\)")/\1(\2)/' \
13| sed -e 's/CONNECTION(\(.*\),[ \t]*"\(.*\)", \(.*\))/NET_C(\1, \2.\3)/' \
14| sed -e 's/CONNECTION("\(.*\)",[ \t]*\(.*\), \(.*\))/NET_C(\1.\2, \3)/' \
15| sed -e 's/NET_C("\(.*\)", \(.*\), \(.*\))/NET_C(\1.\2, \3)/' \
16| sed -e 's/) RES(/)\n    RES(/g' \
17| sed -e 's/) CAP(/)\n    CAP(/g' \
18| sed -e 's/) NET_C(/)\n    NET_C(/g' \
19| sed -e 's/NL_EMPTY//' \
20
21 *
22 */
23
24#ifndef NL_DICE_COMPAT_H_
25#define NL_DICE_COMPAT_H_
26
27#ifndef NL_CONVERT_CPP
28#include "devices/net_lib.h"
29#include "analog/nld_twoterm.h"
30#endif
31
32/* --------------------------------------------------------------------
33 * Compatibility macros for DICE netlists ...
34 * -------------------------------------------------------------------- */
35
36/*
37 * define NETLIST_DEVELOPMENT in IDEs before including this header file
38 * to get compile time errors on unknown devices. This should only be
39 * a temporary support and not be used in commits.
40 */
41
42#ifndef NL_CONVERT_CPP
43#ifndef NETLIST_DEVELOPMENT
44#define NETLIST_DEVELOPMENT 0
45#endif
46#if (NETLIST_DEVELOPMENT)
47#define CHIP(_n, _t) setup.register_dev( palloc(netlist::devices::nld_ ## _t ## _dip), _n);
48#else
49#define CHIP(_n, _t) setup.register_dev(NETLIB_NAME_STR_S(TTL_ ## _t ## _DIP), _n);
50//#define CHIP(_n, _t) TTL_ ## _t ## _DIP(_n)
51#endif
52
53#define CONNECTION( ... ) CONNECTIONY( CONNECTIONX( __VA_ARGS__ ) )
54#define CONNECTIONY(_a) _a
55#define CONNECTIONX(_a, _b, _c, _d) setup.register_link(_a "." # _b, _c "." # _d);
56#define NET_CSTR(_a, _b) setup.register_link( _a, _b);
57
58#define OHM(x) (x)
59#define K_OHM(x) ((x) * 1000.0)
60#define M_OHM(x) ((x) * 1.0e6)
61#define U_FARAD(x) ((x) * 1.0e-6)
62#define N_FARAD(x) ((x) * 1.0e-9)
63#define P_FARAD(x) ((x) * 1.0e-12)
64
65struct Mono555Desc
66{
67public:
68      nl_double r, c;
69
70      Mono555Desc(nl_double res, nl_double cap) : r(res), c(cap) { }
71};
72
73struct Astable555Desc
74{
75public:
76      nl_double r1, r2, c;
77
78      Astable555Desc(nl_double res1, nl_double res2, nl_double cap) : r1(res1), r2(res2), c(cap) { }
79};
80
81struct Mono9602Desc
82{
83public:
84      nl_double r1, c1, r2, c2;
85
86      Mono9602Desc(nl_double res1, nl_double cap1, nl_double res2, nl_double cap2)
87      : r1(res1), c1(cap1), r2(res2), c2(cap2) { }
88};
89
90struct SeriesRCDesc
91{
92public:
93      nl_double r, c;
94
95      SeriesRCDesc(nl_double res, nl_double cap) : r(res), c(cap) { }
96};
97
98struct CapacitorDesc : public SeriesRCDesc
99{
100public:
101   CapacitorDesc(nl_double cap) : SeriesRCDesc(0.0, cap) { }
102};
103
104#else
105#define CHIP(_n, _t) TTL_ ## _t ## _DIP(_n)
106
107#define OHM(x) x
108#define K_OHM(x) RES_K(X)
109#define M_OHM(x) RES_M(X)
110#define U_FARAD(x) CAP_U(x)
111#define N_FARAD(x) CAP_N(x)
112#define P_FARAD(x) CAP_P(x)
113
114#endif
115
116
117#define CIRCUIT_LAYOUT(x) NETLIST_START(x)
118#define CIRCUIT_LAYOUT_END NETLIST_END()
119
120#define CHIP_555_Mono(_name,  _pdesc)   \
121   NE555_DIP(_name) \
122   NET_C(_name.6, _name.7) \
123   RES(_name ## _R, (_pdesc)->r) \
124   CAP(_name ## _C, (_pdesc)->c) \
125   NET_C(_name.6, _name ## _R.1) \
126   NET_C(_name.6, _name ## _C.1) \
127   NET_C(_name ## _R.2, V5) \
128   NET_CSTR(# _name "_C.2", "GND") \
129   NET_C(_name.8, V5) \
130   NET_CSTR(# _name ".1", "GND")
131
132#define CHIP_555_Astable(_name,  _pdesc)   \
133   NE555_DIP(_name) \
134   RES(_name ## _R1, (_pdesc)->r1) \
135   RES(_name ## _R2, (_pdesc)->r2) \
136   CAP(_name ## _C, (_pdesc)->c) \
137   NET_C(_name.7, _name ## _R1.1) \
138   NET_C(_name.7, _name ## _R2.1) \
139   NET_C(_name.6, _name ## _R2.2) \
140   NET_C(_name.6, _name ## _C.1) \
141   NET_C(_name.2, _name ## _C.1) \
142   NET_C(_name ## _R1.2, V5) \
143   NET_CSTR(# _name "_C.2", "GND") \
144   NET_C(_name.8, V5) \
145   NET_CSTR(# _name ".1", "GND")
146
147#define CHIP_9602_Mono(_name,  _pdesc)   \
148   CHIP(# _name, 9602) \
149   NET_C(VCC, _name.16)        \
150   NET_C(GND, _name.8)         \
151   RES(_name ## _R1, (_pdesc)->r1) \
152   CAP(_name ## _C1, (_pdesc)->c1) \
153   RES(_name ## _R2, (_pdesc)->r2) \
154   NET_C(_name.1, _name ## _C1.1) \
155   NET_C(_name.2, _name ## _C1.2) \
156   NET_C(_name.2, _name ## _R1.2) \
157   NET_C(VCC,     _name ## _R1.1) \
158   if (((_pdesc)->c2)>1e-15) { \
159   CAP(_name ## _C2, (_pdesc)->c2) \
160   NET_C(_name.15, _name ## _C2.1) \
161   NET_C(_name.14, _name ## _C2.2) }\
162   NET_C(_name.14, _name ## _R2.2) \
163   NET_C(VCC,     _name ## _R2.1)
164#define CHIP_SERIES_RC(_name,  _pdesc)   \
165   RES(_name ## _R, (_pdesc)->r) \
166   CAP(_name ## _C, (_pdesc)->c) \
167   NET_C(_name ## _R.1, _name ## _C.2) \
168   ALIAS(_name.3, _name ## _R.1) \
169   ALIAS(_name.2, _name ## _R.2) \
170   ALIAS(_name.1, _name ## _C.1)
171
172#define CHIP_INPUT_ACTIVE_LOW(_name)   \
173   SWITCH2(_name ## _SW) \
174   NET_C(_name ## _SW.1, V5) \
175   NET_CSTR(# _name "_SW.2", "GND") \
176   ALIAS(_name.1, _name ## _SW.Q)
177
178#define CHIP_INPUT_ACTIVE_HIGH(_name)   \
179   SWITCH2(_name ## _SW) \
180   NET_C(_name ## _SW.2, V5) \
181   NET_CSTR(# _name "_SW.1", "GND") \
182   ALIAS(_name.1, _name ## _SW.Q)
183
184#define CHIP_LATCH(_name)   \
185   NETDEV_RSFF(_name) \
186   ALIAS(_name.1, _name.R) \
187   ALIAS(_name.2, _name.S) \
188   ALIAS(_name.3, _name.QQ)
189
190/* FIXME: Alternative implementation using capacitor.
191 *        This is a transitional implementation
192 */
193
194inline int CAPACITOR_tc_hl(const double c, const double r)
195{
196   /*
197    * Vt = (VH-VL)*exp(-t/RC)
198    * ln(Vt/(VH-VL))*RC = -t
199    */
200   static const double TIME_CONSTANT = -nl_math::log(2.0 / (3.7-0.3));
201   int ret = (int) (TIME_CONSTANT * (130.0 + r) * c * 1e9);
202   return ret;
203}
204
205inline int CAPACITOR_tc_lh(const double c, const double r)
206{
207   /*
208    * Vt = (VH-VL)*(1-exp(-t/RC))
209    * -t=ln(1-Vt/(VH-VL))*RC
210    */
211   static const double TIME_CONSTANT = -nl_math::log(1.0 - 0.8 / (3.7-0.3));
212   int ret = (int) (TIME_CONSTANT * (1.0 + r) * c * 1e9);
213   return ret;
214}
215
216#define CHIP_CAPACITOR(_name, _pdesc) \
217   NETDEV_DELAY(_name) \
218   NETDEV_PARAMI(_name, L_TO_H, CAPACITOR_tc_lh((_pdesc)->c, (_pdesc)->r)) \
219   NETDEV_PARAMI(_name, H_TO_L, CAPACITOR_tc_hl((_pdesc)->c, (_pdesc)->r))
220
221#endif /* NL_DICE_COMPAT_H_ */
trunk/src/lib/netlist/nl_factory.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/***************************************************************************
4
5    nl_factory.c
6
7    Discrete netlist implementation.
8
9****************************************************************************/
10
11#include "nl_factory.h"
12#include "nl_setup.h"
13
14namespace netlist
15{
16// ----------------------------------------------------------------------------------------
17// net_device_t_base_factory
18// ----------------------------------------------------------------------------------------
19
20ATTR_COLD const pstring_list_t base_factory_t::term_param_list()
21{
22   if (m_def_param.startsWith("+"))
23      return pstring_list_t(m_def_param.substr(1), ",");
24   else
25      return pstring_list_t();
26}
27
28ATTR_COLD const pstring_list_t base_factory_t::def_params()
29{
30   if (m_def_param.startsWith("+") || m_def_param.equals("-"))
31      return pstring_list_t();
32   else
33      return pstring_list_t(m_def_param, ",");
34}
35
36
37factory_list_t::factory_list_t( setup_t &setup)
38: m_setup(setup)
39{
40}
41
42factory_list_t::~factory_list_t()
43{
44   for (std::size_t i=0; i < size(); i++)
45   {
46      base_factory_t *p = value_at(i);
47      pfree(p);
48   }
49   clear();
50}
51
52#if 0
53device_t *factory_list_t::new_device_by_classname(const pstring &classname) const
54{
55   for (std::size_t i=0; i < m_list.size(); i++)
56   {
57      base_factory_t *p = m_list[i];
58      if (p->classname() == classname)
59      {
60         device_t *ret = p->Create();
61         return ret;
62      }
63      p++;
64   }
65   return NULL; // appease code analysis
66}
67#endif
68
69void factory_list_t::error(const pstring &s)
70{
71   m_setup.log().fatal("{1}", s);
72}
73
74device_t *factory_list_t::new_device_by_name(const pstring &name)
75{
76   base_factory_t *f = factory_by_name(name);
77   return f->Create();
78}
79
80base_factory_t * factory_list_t::factory_by_name(const pstring &name)
81{
82   if (contains(name))
83      return (*this)[name];
84   else
85   {
86      m_setup.log().fatal("Class {1} not found!\n", name);
87      return NULL; // appease code analysis
88   }
89}
90
91}
trunk/src/lib/netlist/nl_factory.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nl_factory.h
5 *
6 *
7 */
8
9#ifndef NLFACTORY_H_
10#define NLFACTORY_H_
11
12#include "nl_config.h"
13#include "plib/palloc.h"
14#include "plib/plists.h"
15#include "nl_base.h"
16
17namespace netlist
18{
19   // -----------------------------------------------------------------------------
20   // net_dev class factory
21   // -----------------------------------------------------------------------------
22
23   class base_factory_t
24   {
25      P_PREVENT_COPYING(base_factory_t)
26   public:
27      ATTR_COLD base_factory_t(const pstring &name, const pstring &classname,
28            const pstring &def_param)
29      : m_name(name), m_classname(classname), m_def_param(def_param)
30      {}
31
32      virtual ~base_factory_t() {}
33
34      virtual device_t *Create() = 0;
35
36      ATTR_COLD const pstring &name() const { return m_name; }
37      ATTR_COLD const pstring &classname() const { return m_classname; }
38      ATTR_COLD const pstring &param_desc() const { return m_def_param; }
39      ATTR_COLD const pstring_list_t term_param_list();
40      ATTR_COLD const pstring_list_t def_params();
41
42   protected:
43      pstring m_name;                             /* device name */
44      pstring m_classname;                        /* device class name */
45      pstring m_def_param;                        /* default parameter */
46   };
47
48   template <class C>
49   class factory_t : public base_factory_t
50   {
51      P_PREVENT_COPYING(factory_t)
52   public:
53      ATTR_COLD factory_t(const pstring &name, const pstring &classname,
54            const pstring &def_param)
55      : base_factory_t(name, classname, def_param) { }
56
57      ATTR_COLD device_t *Create()
58      {
59         device_t *r = palloc(C);
60         //r->init(setup, name);
61         return r;
62      }
63   };
64
65   class factory_list_t : public phashmap_t<pstring, base_factory_t *>
66   {
67   public:
68      factory_list_t(setup_t &m_setup);
69      ~factory_list_t();
70
71      template<class _C>
72      ATTR_COLD void register_device(const pstring &name, const pstring &classname,
73            const pstring &def_param)
74      {
75         if (!add(name, palloc(factory_t< _C >(name, classname, def_param))))
76            error("factory already contains " + name);
77      }
78
79      ATTR_COLD void register_device(base_factory_t *factory)
80      {
81         if (!add(factory->name(), factory))
82            error("factory already contains " + factory->name());
83      }
84
85      //ATTR_COLD device_t *new_device_by_classname(const pstring &classname) const;
86      ATTR_COLD device_t *new_device_by_name(const pstring &name);
87      ATTR_COLD base_factory_t * factory_by_name(const pstring &name);
88
89   private:
90      void error(const pstring &s);
91
92      setup_t &m_setup;
93   };
94
95}
96
97#endif /* NLFACTORY_H_ */
trunk/src/lib/netlist/nl_lists.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nllists.h
5 *
6 */
7
8#pragma once
9
10#ifndef NLLISTS_H_
11#define NLLISTS_H_
12
13#include "nl_config.h"
14#include "plib/plists.h"
15
16// ----------------------------------------------------------------------------------------
17// timed queue
18// ----------------------------------------------------------------------------------------
19
20namespace netlist
21{
22   template <class _Element, class _Time>
23   class timed_queue
24   {
25      P_PREVENT_COPYING(timed_queue)
26   public:
27
28      class entry_t
29      {
30      public:
31         ATTR_HOT  entry_t()
32         :  m_exec_time(), m_object() {}
33         ATTR_HOT  entry_t(const _Time &atime, const _Element &elem) : m_exec_time(atime), m_object(elem)  {}
34         ATTR_HOT  const _Time &exec_time() const { return m_exec_time; }
35         ATTR_HOT  const _Element &object() const { return m_object; }
36
37         ATTR_HOT  entry_t &operator=(const entry_t &right) {
38            m_exec_time = right.m_exec_time;
39            m_object = right.m_object;
40            return *this;
41         }
42
43      private:
44         _Time m_exec_time;
45         _Element m_object;
46      };
47
48      timed_queue(unsigned list_size)
49      : m_list(list_size)
50      {
51   #if HAS_OPENMP && USE_OPENMP
52         m_lock = 0;
53   #endif
54         clear();
55      }
56
57      ATTR_HOT  std::size_t capacity() const { return m_list.size(); }
58      ATTR_HOT  bool is_empty() const { return (m_end == &m_list[1]); }
59      ATTR_HOT  bool is_not_empty() const { return (m_end > &m_list[1]); }
60
61      ATTR_HOT void push(const entry_t &e)
62      {
63   #if HAS_OPENMP && USE_OPENMP
64         /* Lock */
65         while (atomic_exchange32(&m_lock, 1)) { }
66   #endif
67         const _Time t = e.exec_time();
68         entry_t * i = m_end++;
69         while (t > (i - 1)->exec_time())
70         {
71            *(i) = *(i-1);
72            i--;
73            inc_stat(m_prof_sortmove);
74         }
75         *i = e;
76         inc_stat(m_prof_call);
77   #if HAS_OPENMP && USE_OPENMP
78         m_lock = 0;
79   #endif
80         //nl_assert(m_end - m_list < _Size);
81      }
82
83      ATTR_HOT  const entry_t *pop()
84      {
85         return --m_end;
86      }
87
88      ATTR_HOT  const entry_t *peek() const
89      {
90         return (m_end-1);
91      }
92
93      ATTR_HOT  void remove(const _Element &elem)
94      {
95         /* Lock */
96   #if HAS_OPENMP && USE_OPENMP
97         while (atomic_exchange32(&m_lock, 1)) { }
98   #endif
99         entry_t * i = m_end - 1;
100         while (i > &m_list[0])
101         {
102            if (i->object() == elem)
103            {
104               m_end--;
105               while (i < m_end)
106               {
107                  *i = *(i+1);
108                  i++;
109               }
110   #if HAS_OPENMP && USE_OPENMP
111               m_lock = 0;
112   #endif
113               return;
114            }
115            i--;
116         }
117   #if HAS_OPENMP && USE_OPENMP
118         m_lock = 0;
119   #endif
120      }
121
122      ATTR_COLD void clear()
123      {
124         m_end = &m_list[0];
125         /* put an empty element with maximum time into the queue.
126          * the insert algo above will run into this element and doesn't
127          * need a comparison with queue start.
128          */
129         m_list[0] = entry_t(_Time::from_raw(~0), _Element(0));
130         m_end++;
131      }
132
133      // save state support & mame disasm
134
135      ATTR_COLD  const entry_t *listptr() const { return &m_list[1]; }
136      ATTR_HOT  int count() const { return m_end - &m_list[1]; }
137      ATTR_HOT  const entry_t & operator[](const int & index) const { return m_list[1+index]; }
138
139   #if (NL_KEEP_STATISTICS)
140      // profiling
141      INT32   m_prof_sortmove;
142      INT32   m_prof_call;
143   #endif
144
145   private:
146
147   #if HAS_OPENMP && USE_OPENMP
148      volatile INT32 m_lock;
149   #endif
150      entry_t * m_end;
151      //entry_t m_list[_Size];
152      parray_t<entry_t> m_list;
153
154   };
155
156}
157
158#endif /* NLLISTS_H_ */
trunk/src/lib/netlist/nl_parser.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nl_parser.c
5 *
6 */
7
8#include "nl_parser.h"
9#include "nl_factory.h"
10#include "devices/nld_truthtable.h"
11
12// for now, make buggy GCC/Mingw STFU about I64FMT
13#if (defined(__MINGW32__) && (__GNUC__ >= 5))
14#pragma GCC diagnostic push
15#pragma GCC diagnostic ignored "-Wformat"
16#pragma GCC diagnostic ignored "-Wformat-extra-args"
17#endif
18
19namespace netlist
20{
21// ----------------------------------------------------------------------------------------
22// A netlist parser
23// ----------------------------------------------------------------------------------------
24
25ATTR_COLD void parser_t::verror(const pstring &msg, int line_num, const pstring &line)
26{
27   m_setup.log().fatal("line {1}: error: {2}\n\t\t{3}\n", line_num,
28         msg, line);
29
30   //throw error;
31}
32
33
34bool parser_t::parse(const pstring nlname)
35{
36   set_identifier_chars("abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_.-");
37   set_number_chars(".0123456789", "0123456789eE-."); //FIXME: processing of numbers
38   char ws[5];
39   ws[0] = ' ';
40   ws[1] = 9;
41   ws[2] = 10;
42   ws[3] = 13;
43   ws[4] = 0;
44   set_whitespace(ws);
45   set_comment("/*", "*/", "//");
46   m_tok_param_left = register_token("(");
47   m_tok_param_right = register_token(")");
48   m_tok_comma = register_token(",");
49
50   m_tok_ALIAS = register_token("ALIAS");
51   m_tok_DIPPINS = register_token("DIPPINS");
52   m_tok_NET_C = register_token("NET_C");
53   m_tok_FRONTIER = register_token("OPTIMIZE_FRONTIER");
54   m_tok_PARAM = register_token("PARAM");
55   m_tok_NET_MODEL = register_token("NET_MODEL");
56   m_tok_INCLUDE = register_token("INCLUDE");
57   m_tok_LOCAL_SOURCE = register_token("LOCAL_SOURCE");
58   m_tok_LOCAL_LIB_ENTRY = register_token("LOCAL_LIB_ENTRY");
59   m_tok_SUBMODEL = register_token("SUBMODEL");
60   m_tok_NETLIST_START = register_token("NETLIST_START");
61   m_tok_NETLIST_END = register_token("NETLIST_END");
62   m_tok_TRUTHTABLE_START = register_token("TRUTHTABLE_START");
63   m_tok_TRUTHTABLE_END = register_token("TRUTHTABLE_END");
64   m_tok_TT_HEAD = register_token("TT_HEAD");
65   m_tok_TT_LINE = register_token("TT_LINE");
66   m_tok_TT_FAMILY = register_token("TT_FAMILY");
67
68   bool in_nl = false;
69
70   while (true)
71   {
72      token_t token = get_token();
73
74      if (token.is_type(ENDOFFILE))
75      {
76         return false;
77         //error("EOF while searching for <{1}>", nlname);
78      }
79
80      if (token.is(m_tok_NETLIST_END))
81      {
82         require_token(m_tok_param_left);
83         if (!in_nl)
84            error("Unexpected NETLIST_END");
85         else
86         {
87            in_nl = false;
88         }
89         require_token(m_tok_param_right);
90      }
91      else if (token.is(m_tok_NETLIST_START))
92      {
93         if (in_nl)
94            error("Unexpected NETLIST_START");
95         require_token(m_tok_param_left);
96         token_t name = get_token();
97         require_token(m_tok_param_right);
98         if (name.str() == nlname || nlname == "")
99         {
100            parse_netlist(name.str());
101            return true;
102         } else
103            in_nl = true;
104      }
105   }
106}
107
108void parser_t::parse_netlist(ATTR_UNUSED const pstring &nlname)
109{
110   while (true)
111   {
112      token_t token = get_token();
113
114      if (token.is_type(ENDOFFILE))
115         return;
116
117      require_token(m_tok_param_left);
118      m_setup.log().debug("Parser: Device: {1}\n", token.str());
119
120      if (token.is(m_tok_ALIAS))
121         net_alias();
122      else if (token.is(m_tok_DIPPINS))
123         dippins();
124      else if (token.is(m_tok_NET_C))
125         net_c();
126      else if (token.is(m_tok_FRONTIER))
127         frontier();
128      else if (token.is(m_tok_PARAM))
129         netdev_param();
130      else if (token.is(m_tok_NET_MODEL))
131         net_model();
132      else if (token.is(m_tok_SUBMODEL))
133         net_submodel();
134      else if (token.is(m_tok_INCLUDE))
135         net_include();
136      else if (token.is(m_tok_LOCAL_SOURCE))
137         net_local_source();
138      else if (token.is(m_tok_TRUTHTABLE_START))
139         net_truthtable_start();
140      else if (token.is(m_tok_LOCAL_LIB_ENTRY))
141      {
142         m_setup.register_lib_entry(get_identifier());
143         require_token(m_tok_param_right);
144      }
145      else if (token.is(m_tok_NETLIST_END))
146      {
147         netdev_netlist_end();
148         return;
149      }
150      else
151         device(token.str());
152   }
153}
154
155void parser_t::net_truthtable_start()
156{
157   pstring name = get_identifier();
158   require_token(m_tok_comma);
159   unsigned ni = get_number_long();
160   require_token(m_tok_comma);
161   unsigned no = get_number_long();
162   require_token(m_tok_comma);
163   unsigned hs = get_number_long();
164   require_token(m_tok_comma);
165   pstring def_param = get_string();
166   require_token(m_tok_param_right);
167
168   netlist::devices::netlist_base_factory_truthtable_t *ttd = netlist::devices::nl_tt_factory_create(ni, no, hs,
169         name, name, "+" + def_param);
170
171   while (true)
172   {
173      token_t token = get_token();
174
175      if (token.is(m_tok_TT_HEAD))
176      {
177         require_token(m_tok_param_left);
178         ttd->m_desc.add(get_string());
179         require_token(m_tok_param_right);
180      }
181      else if (token.is(m_tok_TT_LINE))
182      {
183         require_token(m_tok_param_left);
184         ttd->m_desc.add(get_string());
185         require_token(m_tok_param_right);
186      }
187      else if (token.is(m_tok_TT_FAMILY))
188      {
189         require_token(m_tok_param_left);
190         ttd->m_family = m_setup.family_from_model(get_string());
191         require_token(m_tok_param_right);
192      }
193      else
194      {
195         require_token(token, m_tok_TRUTHTABLE_END);
196         require_token(m_tok_param_left);
197         require_token(m_tok_param_right);
198         m_setup.factory().register_device(ttd);
199         return;
200      }
201   }
202}
203
204
205void parser_t::netdev_netlist_start()
206{
207   // don't do much
208   token_t name = get_token();
209   require_token(m_tok_param_right);
210}
211
212void parser_t::netdev_netlist_end()
213{
214   // don't do much
215   require_token(m_tok_param_right);
216}
217
218void parser_t::net_model()
219{
220   // don't do much
221   pstring model = get_string();
222   m_setup.register_model(model);
223   require_token(m_tok_param_right);
224}
225
226void parser_t::net_submodel()
227{
228   // don't do much
229   pstring model = get_identifier();
230   require_token(m_tok_comma);
231   pstring name = get_identifier();
232   require_token(m_tok_param_right);
233
234   m_setup.namespace_push(name);
235   m_setup.include(model);
236   m_setup.namespace_pop();
237}
238
239void parser_t::frontier()
240{
241   // don't do much
242   pstring attachat = get_identifier();
243   require_token(m_tok_comma);
244   double r_IN = eval_param(get_token());
245   require_token(m_tok_comma);
246   double r_OUT = eval_param(get_token());
247   require_token(m_tok_param_right);
248
249   m_setup.register_frontier(attachat, r_IN, r_OUT);
250}
251
252void parser_t::net_include()
253{
254   // don't do much
255   pstring name = get_identifier();
256   require_token(m_tok_param_right);
257
258   m_setup.include(name);
259}
260
261void parser_t::net_local_source()
262{
263   // This directive is only for hardcoded netlists. Ignore it here.
264   pstring name = get_identifier();
265   require_token(m_tok_param_right);
266
267}
268
269void parser_t::net_alias()
270{
271   pstring alias = get_identifier_or_number();
272
273   require_token(m_tok_comma);
274
275   pstring out = get_identifier();
276
277   require_token(m_tok_param_right);
278
279   m_setup.log().debug("Parser: Alias: {1} {2}\n", alias, out);
280   m_setup.register_alias(alias, out);
281}
282
283void parser_t::net_c()
284{
285   pstring first = get_identifier();
286   require_token(m_tok_comma);
287
288   while (true)
289   {
290      pstring t1 = get_identifier();
291      m_setup.register_link(first , t1);
292      m_setup.log().debug("Parser: Connect: {1} {2}\n", first, t1);
293      token_t n = get_token();
294      if (n.is(m_tok_param_right))
295         break;
296      if (!n.is(m_tok_comma))
297         error(pfmt("expected a comma, found <{1}>")(n.str()) );
298   }
299
300}
301
302void parser_t::dippins()
303{
304   pstring_list_t pins;
305
306   pins.add(get_identifier());
307   require_token(m_tok_comma);
308
309   while (true)
310   {
311      pstring t1 = get_identifier();
312      pins.add(t1);
313      token_t n = get_token();
314      if (n.is(m_tok_param_right))
315         break;
316      if (!n.is(m_tok_comma))
317         error(pfmt("expected a comma, found <{1}>")(n.str()) );
318   }
319   if ((pins.size() % 2) == 1)
320      error("You must pass an equal number of pins to DIPPINS");
321   unsigned n = pins.size();
322   for (unsigned i = 0; i < n / 2; i++)
323   {
324      m_setup.register_alias(pfmt("{1}")(i+1), pins[i*2]);
325      m_setup.register_alias(pfmt("{1}")(n-i), pins[i*2 + 1]);
326   }
327}
328
329void parser_t::netdev_param()
330{
331   pstring param;
332   param = get_identifier();
333   require_token(m_tok_comma);
334   token_t tok = get_token();
335   if (tok.is_type(STRING))
336   {
337      m_setup.log().debug("Parser: Param: {1} {2}\n", param, tok.str());
338      m_setup.register_param(param, tok.str());
339   }
340   else
341   {
342      nl_double val = eval_param(tok);
343      m_setup.log().debug("Parser: Param: {1} {2}\n", param, val);
344      m_setup.register_param(param, val);
345   }
346   require_token(m_tok_param_right);
347}
348
349void parser_t::device(const pstring &dev_type)
350{
351   if (m_setup.is_library_item(dev_type))
352   {
353      pstring devname = get_identifier();
354      m_setup.namespace_push(devname);
355      m_setup.include(dev_type);
356      m_setup.namespace_pop();
357      require_token(m_tok_param_right);
358   }
359   else
360   {
361      base_factory_t *f = m_setup.factory().factory_by_name(dev_type);
362      device_t *dev;
363      pstring_list_t termlist = f->term_param_list();
364      pstring_list_t def_params = f->def_params();
365
366      std::size_t cnt;
367
368      pstring devname = get_identifier();
369
370      dev = f->Create();
371      m_setup.register_dev(dev, devname);
372
373      m_setup.log().debug("Parser: IC: {1}\n", devname);
374
375      cnt = 0;
376      while (cnt < def_params.size())
377      {
378         pstring paramfq = devname + "." + def_params[cnt];
379
380         m_setup.log().debug("Defparam: {1}\n", paramfq);
381         require_token(m_tok_comma);
382         token_t tok = get_token();
383         if (tok.is_type(STRING))
384         {
385            m_setup.register_param(paramfq, tok.str());
386         }
387         else
388         {
389            nl_double val = eval_param(tok);
390            m_setup.register_param(paramfq, val);
391         }
392         cnt++;
393      }
394
395      token_t tok = get_token();
396      cnt = 0;
397      while (tok.is(m_tok_comma) && cnt < termlist.size())
398      {
399         pstring output_name = get_identifier();
400
401         m_setup.register_link(devname + "." + termlist[cnt], output_name);
402
403         cnt++;
404         tok = get_token();
405      }
406      if (cnt != termlist.size())
407         m_setup.log().fatal("netlist: input count mismatch for {1} - expected {2} found {3}\n", devname, termlist.size(), cnt);
408      require_token(tok, m_tok_param_right);
409   }
410}
411
412
413// ----------------------------------------------------------------------------------------
414// private
415// ----------------------------------------------------------------------------------------
416
417
418nl_double parser_t::eval_param(const token_t tok)
419{
420   static const char *macs[6] = {"", "RES_K", "RES_M", "CAP_U", "CAP_N", "CAP_P"};
421   static nl_double facs[6] = {1, 1e3, 1e6, 1e-6, 1e-9, 1e-12};
422   int i;
423   int f=0;
424   bool e;
425   nl_double ret;
426   pstring val;
427
428   //printf("param {1}\n", tok.m_token);
429   for (i=1; i<6;i++)
430      if (tok.str().equals(macs[i]))
431         f = i;
432#if 1
433   if (f>0)
434   {
435      require_token(m_tok_param_left);
436      ret = get_number_double();
437      require_token(m_tok_param_right);
438   }
439   else
440   {
441      val = tok.str();
442      ret = val.as_double(&e);
443      if (e)
444         error("Error with parameter ...\n");
445   }
446   return ret * facs[f];
447
448#else
449   if (f>0)
450   {
451      require_token(m_tok_param_left);
452      val = get_identifier();
453   }
454   else
455      val = tok.str();
456
457   ret = val.as_double(&e);
458
459   if (e)
460      fatal("Error with parameter ...\n");
461   if (f>0)
462      require_token(m_tok_param_right);
463   return ret * facs[f];
464#endif
465}
466}
467
468#if (defined(__MINGW32__) && (__GNUC__ >= 5))
469#pragma GCC diagnostic pop
470#endif
trunk/src/lib/netlist/nl_parser.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nl_parser.c
5 *
6 */
7
8#ifndef NL_PARSER_H_
9#define NL_PARSER_H_
10
11#include "nl_setup.h"
12#include "nl_util.h"
13#include "plib/pparser.h"
14
15namespace netlist
16{
17   class parser_t : public ptokenizer
18   {
19      P_PREVENT_COPYING(parser_t)
20   public:
21      parser_t(pistream &strm, setup_t &setup)
22      : ptokenizer(strm), m_setup(setup), m_buf(NULL) {}
23
24      bool parse(const pstring nlname = "");
25
26   protected:
27      void parse_netlist(const pstring &nlname);
28      void net_alias();
29      void dippins();
30      void netdev_param();
31      void net_c();
32      void frontier();
33      void device(const pstring &dev_type);
34      void netdev_netlist_start();
35      void netdev_netlist_end();
36      void net_model();
37      void net_submodel();
38      void net_include();
39      void net_local_source();
40      void net_truthtable_start();
41
42      /* for debugging messages */
43      netlist_t &netlist() { return m_setup.netlist(); }
44
45      virtual void verror(const pstring &msg, int line_num, const pstring &line);
46   private:
47
48      nl_double eval_param(const token_t tok);
49
50      token_id_t m_tok_param_left;
51      token_id_t m_tok_param_right;
52      token_id_t m_tok_comma;
53      token_id_t m_tok_ALIAS;
54      token_id_t m_tok_NET_C;
55      token_id_t m_tok_DIPPINS;
56      token_id_t m_tok_FRONTIER;
57      token_id_t m_tok_PARAM;
58      token_id_t m_tok_NET_MODEL;
59      token_id_t m_tok_NETLIST_START;
60      token_id_t m_tok_NETLIST_END;
61      token_id_t m_tok_SUBMODEL;
62      token_id_t m_tok_INCLUDE;
63      token_id_t m_tok_LOCAL_SOURCE;
64      token_id_t m_tok_LOCAL_LIB_ENTRY;
65      token_id_t m_tok_TRUTHTABLE_START;
66      token_id_t m_tok_TRUTHTABLE_END;
67      token_id_t m_tok_TT_HEAD;
68      token_id_t m_tok_TT_LINE;
69      token_id_t m_tok_TT_FAMILY;
70
71      setup_t &m_setup;
72
73      const char *m_buf;
74   };
75
76}
77
78#endif /* NL_PARSER_H_ */
trunk/src/lib/netlist/nl_setup.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nlsetup.c
5 *
6 */
7
8#include <cstdio>
9
10#include "solver/nld_solver.h"
11
12#include "plib/palloc.h"
13#include "nl_base.h"
14#include "nl_setup.h"
15#include "nl_parser.h"
16#include "nl_util.h"
17#include "nl_factory.h"
18#include "devices/net_lib.h"
19#include "devices/nld_system.h"
20#include "analog/nld_twoterm.h"
21
22static NETLIST_START(base)
23   TTL_INPUT(ttlhigh, 1)
24   TTL_INPUT(ttllow, 0)
25   NET_REGISTER_DEV(GND, GND)
26   NET_REGISTER_DEV(PARAMETER, NETLIST)
27
28   LOCAL_SOURCE(diode_models)
29   LOCAL_SOURCE(bjt_models)
30   LOCAL_SOURCE(family_models)
31   LOCAL_SOURCE(TTL74XX_lib)
32   LOCAL_SOURCE(CD4XXX_lib)
33   LOCAL_SOURCE(OPAMP_lib)
34   LOCAL_SOURCE(otheric_lib)
35
36   INCLUDE(diode_models);
37   INCLUDE(bjt_models);
38   INCLUDE(family_models);
39   INCLUDE(TTL74XX_lib);
40   INCLUDE(CD4XXX_lib);
41   INCLUDE(OPAMP_lib);
42   INCLUDE(otheric_lib);
43
44NETLIST_END()
45
46
47// ----------------------------------------------------------------------------------------
48// setup_t
49// ----------------------------------------------------------------------------------------
50
51namespace netlist
52{
53setup_t::setup_t(netlist_t *netlist)
54   : m_netlist(netlist)
55   , m_proxy_cnt(0)
56{
57   netlist->set_setup(this);
58   m_factory = palloc(factory_list_t(*this));
59}
60
61void setup_t::init()
62{
63   initialize_factory(factory());
64   NETLIST_NAME(base)(*this);
65}
66
67
68setup_t::~setup_t()
69{
70   m_links.clear();
71   m_alias.clear();
72   m_params.clear();
73   m_terminals.clear();
74   m_params_temp.clear();
75
76   netlist().set_setup(NULL);
77   pfree(m_factory);
78   m_sources.clear_and_free();
79
80   pstring::resetmem();
81}
82
83ATTR_COLD pstring setup_t::build_fqn(const pstring &obj_name) const
84{
85   if (m_stack.empty())
86      return netlist().name() + "." + obj_name;
87   else
88      return m_stack.peek() + "." + obj_name;
89}
90
91void setup_t::namespace_push(const pstring &aname)
92{
93   if (m_stack.empty())
94      m_stack.push(netlist().name() + "." + aname);
95   else
96      m_stack.push(m_stack.peek() + "." + aname);
97}
98
99void setup_t::namespace_pop()
100{
101   m_stack.pop();
102}
103
104
105device_t *setup_t::register_dev(device_t *dev, const pstring &name)
106{
107   pstring fqn = build_fqn(name);
108
109   dev->init(netlist(), fqn);
110
111   if (!(netlist().m_devices.add(dev, false)==true))
112      log().fatal("Error adding {1} to device list\n", name);
113   return dev;
114}
115
116void setup_t::register_lib_entry(const pstring &name)
117{
118   if (m_lib.contains(name))
119      log().warning("Lib entry collection already contains {1}. IGNORED", name);
120   else
121      m_lib.add(name);
122}
123
124device_t *setup_t::register_dev(const pstring &classname, const pstring &name)
125{
126   if (m_lib.contains(classname))
127   {
128      namespace_push(name);
129      include(classname);
130      namespace_pop();
131      return NULL;
132   }
133   else
134   {
135      device_t *dev = factory().new_device_by_name(classname);
136      //device_t *dev = factory().new_device_by_classname(classname);
137      if (dev == NULL)
138         log().fatal("Class {1} not found!\n", classname);
139      return register_dev(dev, name);
140   }
141}
142
143void setup_t::register_model(const pstring &model_in)
144{
145   int pos = model_in.find(" ");
146   if (pos < 0)
147      log().fatal("Unable to parse model: {1}", model_in);
148   pstring model = model_in.left(pos).trim().ucase();
149   pstring def = model_in.substr(pos + 1).trim();
150   if (!m_models.add(model, def))
151      log().fatal("Model already exists: {1}", model_in);
152}
153
154void setup_t::register_alias_nofqn(const pstring &alias, const pstring &out)
155{
156   if (!m_alias.add(alias, out))
157      log().fatal("Error adding alias {1} to alias list\n", alias);
158}
159
160void setup_t::register_alias(const pstring &alias, const pstring &out)
161{
162   pstring alias_fqn = build_fqn(alias);
163   pstring out_fqn = build_fqn(out);
164   register_alias_nofqn(alias_fqn, out_fqn);
165}
166
167void setup_t::register_dippins_arr(const pstring &terms)
168{
169   pstring_list_t list(terms,", ");
170   if (list.size() == 0 || (list.size() % 2) == 1)
171      log().fatal("You must pass an equal number of pins to DIPPINS");
172   unsigned n = list.size();
173   for (unsigned i = 0; i < n / 2; i++)
174   {
175      register_alias(pfmt("{1}")(i+1), list[i * 2]);
176      register_alias(pfmt("{1}")(n-i), list[i * 2 + 1]);
177   }
178}
179
180pstring setup_t::objtype_as_astr(object_t &in) const
181{
182   switch (in.type())
183   {
184      case terminal_t::TERMINAL:
185         return "TERMINAL";
186      case terminal_t::INPUT:
187         return "INPUT";
188      case terminal_t::OUTPUT:
189         return "OUTPUT";
190      case terminal_t::NET:
191         return "NET";
192      case terminal_t::PARAM:
193         return "PARAM";
194      case terminal_t::DEVICE:
195         return "DEVICE";
196      case terminal_t::NETLIST:
197         return "NETLIST";
198      case terminal_t::QUEUE:
199         return "QUEUE";
200   }
201   // FIXME: noreturn
202   log().fatal("Unknown object type {1}\n", (unsigned) in.type());
203   return "Error";
204}
205
206
207void setup_t::register_object(device_t &dev, const pstring &name, object_t &obj)
208{
209   switch (obj.type())
210   {
211      case terminal_t::TERMINAL:
212      case terminal_t::INPUT:
213      case terminal_t::OUTPUT:
214         {
215            core_terminal_t &term = dynamic_cast<core_terminal_t &>(obj);
216            if (obj.isType(terminal_t::OUTPUT))
217            {
218               if (obj.isFamily(terminal_t::LOGIC))
219                  dynamic_cast<logic_output_t &>(term).init_object(dev, dev.name() + "." + name);
220               else if (obj.isFamily(terminal_t::ANALOG))
221                  dynamic_cast<analog_output_t &>(term).init_object(dev, dev.name() + "." + name);
222               else
223                  log().fatal("Error adding {1} {2} to terminal list, neither LOGIC nor ANALOG\n", objtype_as_astr(term), term.name());
224            }
225            else
226               term.init_object(dev, dev.name() + "." + name);
227
228            if (!m_terminals.add(term.name(), &term))
229               log().fatal("Error adding {1} {2} to terminal list\n", objtype_as_astr(term), term.name());
230            log().debug("{1} {2}\n", objtype_as_astr(term), name);
231         }
232         break;
233      case terminal_t::NET:
234         break;
235      case terminal_t::PARAM:
236         {
237            param_t &param = dynamic_cast<param_t &>(obj);
238            //printf("name: {1}\n", name);
239            if (m_params_temp.contains(name))
240            {
241               const pstring val = m_params_temp[name];
242               switch (param.param_type())
243               {
244                  case param_t::DOUBLE:
245                  {
246                     log().debug("Found parameter ... {1} : {1}\n", name, val);
247                     double vald = 0;
248                     if (sscanf(val.cstr(), "%lf", &vald) != 1)
249                        log().fatal("Invalid number conversion {1} : {2}\n", name, val);
250                     dynamic_cast<param_double_t &>(param).initial(vald);
251                  }
252                  break;
253                  case param_t::INTEGER:
254                  case param_t::LOGIC:
255                  {
256                     log().debug("Found parameter ... {1} : {2}\n", name, val);
257                     double vald = 0;
258                     if (sscanf(val.cstr(), "%lf", &vald) != 1)
259                        log().fatal("Invalid number conversion {1} : {2}\n", name, val);
260                     dynamic_cast<param_int_t &>(param).initial((int) vald);
261                  }
262                  break;
263                  case param_t::STRING:
264                  {
265                     dynamic_cast<param_str_t &>(param).initial(val);
266                  }
267                  break;
268                  case param_t::MODEL:
269                     //dynamic_cast<param_model_t &>(param).initial(val);
270                     dynamic_cast<param_model_t &>(param).initial(val);
271                     break;
272                  default:
273                     log().fatal("Parameter is not supported {1} : {2}\n", name, val);
274               }
275            }
276            if (!m_params.add(param.name(), &param))
277               log().fatal("Error adding parameter {1} to parameter list\n", name);
278         }
279         break;
280      case terminal_t::DEVICE:
281         log().fatal("Device registration not yet supported - {1}\n", name);
282         break;
283      case terminal_t::NETLIST:
284         log().fatal("Netlist registration not yet supported - {1}\n", name);
285         break;
286      case terminal_t::QUEUE:
287         log().fatal("QUEUE registration not yet supported - {1}\n", name);
288         break;
289   }
290}
291
292void setup_t::register_link_arr(const pstring &terms)
293{
294   pstring_list_t list(terms,", ");
295   if (list.size() < 2)
296      log().fatal("You must pass at least 2 terminals to NET_C");
297   for (std::size_t i = 1; i < list.size(); i++)
298   {
299      register_link(list[0], list[i]);
300   }
301}
302
303
304void setup_t::register_link_fqn(const pstring &sin, const pstring &sout)
305{
306   link_t temp = link_t(sin, sout);
307   log().debug("link {1} <== {2}\n", sin, sout);
308   m_links.add(temp);
309}
310
311void setup_t::register_link(const pstring &sin, const pstring &sout)
312{
313   register_link_fqn(build_fqn(sin), build_fqn(sout));
314}
315
316void setup_t::remove_connections(const pstring pin)
317{
318   pstring pinfn = build_fqn(pin);
319   bool found = false;
320   for (std::size_t i = 0; i < m_links.size(); i++)
321   {
322      if ((m_links[i].e1 == pinfn) || (m_links[i].e2 == pinfn))
323      {
324         log().verbose("removing connection: {1} <==> {2}\n", m_links[i].e1, m_links[i].e2);
325         m_links.remove_at(i);
326         found = true;
327      }
328   }
329   if (!found)
330      log().fatal("remove_connections: found no occurrence of {1}\n", pin);
331}
332
333
334void setup_t::register_frontier(const pstring attach, const double r_IN, const double r_OUT)
335{
336   static int frontier_cnt = 0;
337   pstring frontier_name = pfmt("frontier_{1}")(frontier_cnt);
338   frontier_cnt++;
339   device_t *front = register_dev("FRONTIER_DEV", frontier_name);
340   register_param(frontier_name + ".RIN", r_IN);
341   register_param(frontier_name + ".ROUT", r_OUT);
342   register_link(frontier_name + ".G", "GND");
343   pstring attfn = build_fqn(attach);
344   bool found = false;
345   for (std::size_t i = 0; i < m_links.size(); i++)
346   {
347      if (m_links[i].e1 == attfn)
348      {
349         m_links[i].e1 = front->name() + ".I";
350         found = true;
351      }
352      else if (m_links[i].e2 == attfn)
353      {
354         m_links[i].e2 = front->name() + ".I";
355         found = true;
356      }
357   }
358   if (!found)
359      log().fatal("Frontier setup: found no occurrence of {1}\n", attach);
360   register_link(attach, frontier_name + ".Q");
361}
362
363
364void setup_t::register_param(const pstring &param, const double value)
365{
366   // FIXME: there should be a better way
367   register_param(param, pfmt("{1}").e(value,".9"));
368}
369
370void setup_t::register_param(const pstring &param, const pstring &value)
371{
372   pstring fqn = build_fqn(param);
373
374   int idx = m_params_temp.index_of(fqn);
375   if (idx < 0)
376   {
377      if (!m_params_temp.add(fqn, value))
378         log().fatal("Unexpected error adding parameter {1} to parameter list\n", param);
379   }
380   else
381   {
382      log().warning("Overwriting {1} old <{2}> new <{3}>\n", fqn, m_params_temp.value_at(idx), value);
383      m_params_temp[fqn] = value;
384   }
385}
386
387const pstring setup_t::resolve_alias(const pstring &name) const
388{
389   pstring temp = name;
390   pstring ret;
391
392   /* FIXME: Detect endless loop */
393   do {
394      ret = temp;
395      int p = m_alias.index_of(ret);
396      temp = (p>=0 ? m_alias.value_at(p) : "");
397   } while (temp != "");
398
399   log().debug("{1}==>{2}\n", name, ret);
400   return ret;
401}
402
403core_terminal_t *setup_t::find_terminal(const pstring &terminal_in, bool required)
404{
405   const pstring &tname = resolve_alias(terminal_in);
406   int ret;
407
408   ret = m_terminals.index_of(tname);
409   /* look for default */
410   if (ret < 0)
411   {
412      /* look for ".Q" std output */
413      ret = m_terminals.index_of(tname + ".Q");
414   }
415
416   core_terminal_t *term = (ret < 0 ? NULL : m_terminals.value_at(ret));
417
418   if (term == NULL && required)
419      log().fatal("terminal {1}({2}) not found!\n", terminal_in, tname);
420   if (term != NULL)
421      log().debug("Found input {1}\n", tname);
422   return term;
423}
424
425core_terminal_t *setup_t::find_terminal(const pstring &terminal_in, object_t::type_t atype, bool required)
426{
427   const pstring &tname = resolve_alias(terminal_in);
428   int ret;
429
430   ret = m_terminals.index_of(tname);
431   /* look for default */
432   if (ret < 0 && atype == object_t::OUTPUT)
433   {
434      /* look for ".Q" std output */
435      ret = m_terminals.index_of(tname + ".Q");
436   }
437   if (ret < 0 && required)
438      log().fatal("terminal {1}({2}) not found!\n", terminal_in, tname);
439
440   core_terminal_t *term = (ret < 0 ? NULL : m_terminals.value_at(ret));
441
442   if (term != NULL && term->type() != atype)
443   {
444      if (required)
445         log().fatal("object {1}({2}) found but wrong type\n", terminal_in, tname);
446      else
447         term = NULL;
448   }
449   if (term != NULL)
450      log().debug("Found input {1}\n", tname);
451
452   return term;
453}
454
455param_t *setup_t::find_param(const pstring &param_in, bool required)
456{
457   const pstring param_in_fqn = build_fqn(param_in);
458
459   const pstring &outname = resolve_alias(param_in_fqn);
460   int ret;
461
462   ret = m_params.index_of(outname);
463   if (ret < 0 && required)
464      log().fatal("parameter {1}({2}) not found!\n", param_in_fqn, outname);
465   if (ret != -1)
466      log().debug("Found parameter {1}\n", outname);
467   return (ret == -1 ? NULL : m_params.value_at(ret));
468}
469
470// FIXME avoid dynamic cast here
471devices::nld_base_proxy *setup_t::get_d_a_proxy(core_terminal_t &out)
472{
473   nl_assert(out.isFamily(terminal_t::LOGIC));
474
475   //printf("proxy for {1}\n", out.name());;
476   logic_output_t &out_cast = dynamic_cast<logic_output_t &>(out);
477   devices::nld_base_proxy *proxy = out_cast.get_proxy();
478
479   if (proxy == NULL)
480   {
481      // create a new one ...
482      devices::nld_base_d_to_a_proxy *new_proxy = out_cast.logic_family()->create_d_a_proxy(&out_cast);
483      pstring x = pfmt("proxy_da_{1}_{2}")(out.name())(m_proxy_cnt);
484      m_proxy_cnt++;
485
486      register_dev(new_proxy, x);
487      new_proxy->start_dev();
488
489#if 1
490      /* connect all existing terminals to new net */
491
492      for (std::size_t i = 0; i < out.net().m_core_terms.size(); i++)
493      {
494         core_terminal_t *p = out.net().m_core_terms[i];
495         p->clear_net(); // de-link from all nets ...
496         if (!connect(new_proxy->proxy_term(), *p))
497            log().fatal("Error connecting {1} to {2}\n", new_proxy->proxy_term().name(), (*p).name());
498      }
499      out.net().m_core_terms.clear(); // clear the list
500#endif
501      out.net().register_con(new_proxy->in());
502      out_cast.set_proxy(new_proxy);
503      proxy = new_proxy;
504   }
505   return proxy;
506}
507
508void setup_t::connect_input_output(core_terminal_t &in, core_terminal_t &out)
509{
510   if (out.isFamily(terminal_t::ANALOG) && in.isFamily(terminal_t::LOGIC))
511   {
512      logic_input_t &incast = dynamic_cast<logic_input_t &>(in);
513      devices::nld_a_to_d_proxy *proxy = palloc(devices::nld_a_to_d_proxy(&incast));
514      incast.set_proxy(proxy);
515      pstring x = pfmt("proxy_ad_{1}_{2}")(in.name())( m_proxy_cnt);
516      m_proxy_cnt++;
517
518      register_dev(proxy, x);
519      proxy->start_dev();
520
521      proxy->m_Q.net().register_con(in);
522      out.net().register_con(proxy->m_I);
523
524   }
525   else if (out.isFamily(terminal_t::LOGIC) && in.isFamily(terminal_t::ANALOG))
526   {
527      devices::nld_base_proxy *proxy = get_d_a_proxy(out);
528
529      connect_terminals(proxy->proxy_term(), in);
530      //proxy->out().net().register_con(in);
531   }
532   else
533   {
534      if (in.has_net())
535         out.net().merge_net(&in.net());
536      else
537         out.net().register_con(in);
538   }
539}
540
541
542void setup_t::connect_terminal_input(terminal_t &term, core_terminal_t &inp)
543{
544   if (inp.isFamily(terminal_t::ANALOG))
545   {
546      connect_terminals(inp, term);
547   }
548   else if (inp.isFamily(terminal_t::LOGIC))
549   {
550      logic_input_t &incast = dynamic_cast<logic_input_t &>(inp);
551      log().debug("connect_terminal_input: connecting proxy\n");
552      devices::nld_a_to_d_proxy *proxy = palloc(devices::nld_a_to_d_proxy(&incast));
553      incast.set_proxy(proxy);
554      pstring x = pfmt("proxy_ad_{1}_{2}")(inp.name())(m_proxy_cnt);
555      m_proxy_cnt++;
556
557      register_dev(proxy, x);
558      proxy->start_dev();
559
560      connect_terminals(term, proxy->m_I);
561
562      if (inp.has_net())
563         //fatalerror("logic inputs can only belong to one net!\n");
564         proxy->m_Q.net().merge_net(&inp.net());
565      else
566         proxy->m_Q.net().register_con(inp);
567   }
568   else
569   {
570      log().fatal("Netlist: Severe Error");
571   }
572}
573
574void setup_t::connect_terminal_output(terminal_t &in, core_terminal_t &out)
575{
576   if (out.isFamily(terminal_t::ANALOG))
577   {
578      log().debug("connect_terminal_output: {1} {2}\n", in.name(), out.name());
579      /* no proxy needed, just merge existing terminal net */
580      if (in.has_net())
581         out.net().merge_net(&in.net());
582      else
583         out.net().register_con(in);
584   }
585   else if (out.isFamily(terminal_t::LOGIC))
586   {
587      log().debug("connect_terminal_output: connecting proxy\n");
588      devices::nld_base_proxy *proxy = get_d_a_proxy(out);
589
590      connect_terminals(proxy->proxy_term(), in);
591   }
592   else
593   {
594      log().fatal("Netlist: Severe Error");
595   }
596}
597
598void setup_t::connect_terminals(core_terminal_t &t1, core_terminal_t &t2)
599{
600   //nl_assert(in.isType(netlist_terminal_t::TERMINAL));
601   //nl_assert(out.isType(netlist_terminal_t::TERMINAL));
602
603   if (t1.has_net() && t2.has_net())
604   {
605      log().debug("T2 and T1 have net\n");
606      t1.net().merge_net(&t2.net());
607   }
608   else if (t2.has_net())
609   {
610      log().debug("T2 has net\n");
611      t2.net().register_con(t1);
612   }
613   else if (t1.has_net())
614   {
615      log().debug("T1 has net\n");
616      t1.net().register_con(t2);
617   }
618   else
619   {
620      log().debug("adding net ...\n");
621      analog_net_t *anet =  palloc(analog_net_t);
622      t1.set_net(*anet);
623      //m_netlist.solver()->m_nets.add(anet);
624      // FIXME: Nets should have a unique name
625      t1.net().init_object(netlist(),"net." + t1.name() );
626      t1.net().register_con(t2);
627      t1.net().register_con(t1);
628   }
629}
630
631static core_terminal_t &resolve_proxy(core_terminal_t &term)
632{
633   if (term.isFamily(core_terminal_t::LOGIC))
634   {
635      logic_t &out = dynamic_cast<logic_t &>(term);
636      if (out.has_proxy())
637         return out.get_proxy()->proxy_term();
638   }
639   return term;
640}
641
642bool setup_t::connect_input_input(core_terminal_t &t1, core_terminal_t &t2)
643{
644   bool ret = false;
645   if (t1.has_net())
646   {
647      if (t1.net().isRailNet())
648         ret = connect(t2, t1.net().railterminal());
649      if (!ret)
650      {
651         for (std::size_t i=0; i<t1.net().m_core_terms.size(); i++)
652         {
653            if (t1.net().m_core_terms[i]->isType(core_terminal_t::TERMINAL)
654                  /*|| t1.net().m_core_terms[i]->isType(netlist_core_terminal_t::OUTPUT)*/)
655            {
656               ret = connect(t2, *t1.net().m_core_terms[i]);
657            }
658            if (ret)
659               break;
660         }
661      }
662   }
663   if (!ret && t2.has_net())
664   {
665      if (t2.net().isRailNet())
666         ret = connect(t1, t2.net().railterminal());
667      if (!ret)
668      {
669         for (std::size_t i=0; i<t2.net().m_core_terms.size(); i++)
670         {
671            if (t2.net().m_core_terms[i]->isType(core_terminal_t::TERMINAL)
672                  /*|| t2.net().m_core_terms[i]->isType(netlist_core_terminal_t::OUTPUT)*/)
673            {
674               ret = connect(t1, *t2.net().m_core_terms[i]);
675            }
676            if (ret)
677               break;
678         }
679      }
680   }
681   return ret;
682}
683
684
685
686bool setup_t::connect(core_terminal_t &t1_in, core_terminal_t &t2_in)
687{
688   log().debug("Connecting {1} to {2}\n", t1_in.name(), t2_in.name());
689   core_terminal_t &t1 = resolve_proxy(t1_in);
690   core_terminal_t &t2 = resolve_proxy(t2_in);
691   bool ret = true;
692
693   if (t1.isType(core_terminal_t::OUTPUT) && t2.isType(core_terminal_t::INPUT))
694   {
695      if (t2.has_net() && t2.net().isRailNet())
696         log().fatal("Input {1} already connected\n", t2.name());
697      connect_input_output(t2, t1);
698   }
699   else if (t1.isType(core_terminal_t::INPUT) && t2.isType(core_terminal_t::OUTPUT))
700   {
701      if (t1.has_net()  && t1.net().isRailNet())
702         log().fatal("Input {1} already connected\n", t1.name());
703      connect_input_output(t1, t2);
704   }
705   else if (t1.isType(core_terminal_t::OUTPUT) && t2.isType(core_terminal_t::TERMINAL))
706   {
707      connect_terminal_output(dynamic_cast<terminal_t &>(t2), t1);
708   }
709   else if (t1.isType(core_terminal_t::TERMINAL) && t2.isType(core_terminal_t::OUTPUT))
710   {
711      connect_terminal_output(dynamic_cast<terminal_t &>(t1), t2);
712   }
713   else if (t1.isType(core_terminal_t::INPUT) && t2.isType(core_terminal_t::TERMINAL))
714   {
715      connect_terminal_input(dynamic_cast<terminal_t &>(t2), t1);
716   }
717   else if (t1.isType(core_terminal_t::TERMINAL) && t2.isType(core_terminal_t::INPUT))
718   {
719      connect_terminal_input(dynamic_cast<terminal_t &>(t1), t2);
720   }
721   else if (t1.isType(core_terminal_t::TERMINAL) && t2.isType(core_terminal_t::TERMINAL))
722   {
723      connect_terminals(dynamic_cast<terminal_t &>(t1), dynamic_cast<terminal_t &>(t2));
724   }
725   else if (t1.isType(core_terminal_t::INPUT) && t2.isType(core_terminal_t::INPUT))
726   {
727      ret = connect_input_input(t1, t2);
728   }
729   else
730      ret = false;
731      //netlist().error("Connecting {1} to {2} not supported!\n", t1.name(), t2.name());
732   return ret;
733}
734
735void setup_t::resolve_inputs()
736{
737   bool has_twoterms = false;
738
739   log().verbose("Resolving inputs ...");
740
741   /* Netlist can directly connect input to input.
742    * We therefore first park connecting inputs and retry
743    * after all other terminals were connected.
744    */
745   int tries = 100;
746   while (m_links.size() > 0 && tries >  0) // FIXME: convert into constant
747   {
748      unsigned li = 0;
749      while (li < m_links.size())
750      {
751         const pstring t1s = m_links[li].e1;
752         const pstring t2s = m_links[li].e2;
753         core_terminal_t *t1 = find_terminal(t1s);
754         core_terminal_t *t2 = find_terminal(t2s);
755
756         if (connect(*t1, *t2))
757            m_links.remove_at(li);
758         else
759            li++;
760      }
761      tries--;
762   }
763   if (tries == 0)
764   {
765      for (std::size_t i = 0; i < m_links.size(); i++ )
766         log().warning("Error connecting {1} to {2}\n", m_links[i].e1, m_links[i].e2);
767
768      log().fatal("Error connecting -- bailing out\n");
769   }
770
771   log().verbose("deleting empty nets ...");
772
773   // delete empty nets ... and save m_list ...
774
775   net_t::list_t todelete;
776
777   for (std::size_t i = 0; i<netlist().m_nets.size(); i++)
778   {
779      if (netlist().m_nets[i]->num_cons() == 0)
780      {
781         todelete.add(netlist().m_nets[i]);
782      }
783      else
784      {
785         netlist().m_nets[i]->rebuild_list();
786      }
787   }
788
789   for (std::size_t i=0; i < todelete.size(); i++)
790   {
791      log().verbose("Deleting net {1} ...", todelete[i]->name());
792      netlist().m_nets.remove(todelete[i]);
793      if (!todelete[i]->isRailNet())
794         pfree(todelete[i]);
795   }
796
797   pstring errstr("");
798
799   log().verbose("looking for terminals not connected ...");
800   for (std::size_t i = 0; i < m_terminals.size(); i++)
801   {
802      core_terminal_t *term = m_terminals.value_at(i);
803      if (!term->has_net())
804         errstr += pfmt("Found terminal {1} without a net\n")(term->name());
805      else if (term->net().num_cons() == 0)
806         log().warning("Found terminal {1} without connections",
807               term->name());
808   }
809   if (errstr != "")
810      log().fatal("{1}", errstr);
811
812
813   log().verbose("looking for two terms connected to rail nets ...\n");
814   // FIXME: doesn't find internal devices. This needs to be more clever
815   for (std::size_t i=0; i < netlist().m_devices.size(); i++)
816   {
817      devices::NETLIB_NAME(twoterm) *t = dynamic_cast<devices::NETLIB_NAME(twoterm) *>(netlist().m_devices[i]);
818      if (t != NULL)
819      {
820         has_twoterms = true;
821         if (t->m_N.net().isRailNet() && t->m_P.net().isRailNet())
822#if 0
823            netlist().fatal("Found device {1} connected only to railterminals {2}/{3}\n",
824                  t->name(), t->m_N.net().name(), t->m_P.net().name());
825#else
826            log().warning("Found device {1} connected only to railterminals {2}/{3}\n",
827               t->name(), t->m_N.net().name(), t->m_P.net().name());
828#endif
829      }
830   }
831
832   log().verbose("initialize solver ...\n");
833
834   if (netlist().solver() == NULL)
835   {
836      if (has_twoterms)
837         log().fatal("No solver found for this net although analog elements are present\n");
838   }
839   else
840      netlist().solver()->post_start();
841
842}
843
844void setup_t::start_devices()
845{
846   pstring env = nl_util::environment("NL_LOGS");
847
848   if (env != "")
849   {
850      log().debug("Creating dynamic logs ...\n");
851      pstring_list_t ll(env, ":");
852      for (unsigned i=0; i < ll.size(); i++)
853      {
854         log().debug("{1}: <{2}>\n",i, ll[i]);
855         log().debug("{1}: <{2}>\n",i, ll[i]);
856         device_t *nc = factory().new_device_by_name("LOG");
857         pstring name = "log_" + ll[i];
858         register_dev(nc, name);
859         register_link(name + ".I", ll[i]);
860      }
861   }
862
863   netlist().start();
864}
865
866void setup_t::print_stats() const
867{
868#if (NL_KEEP_STATISTICS)
869   {
870      for (std::size_t i = 0; i < netlist().m_started_devices.size(); i++)
871      {
872         core_device_t *entry = netlist().m_started_devices[i];
873         printf("Device %20s : %12d %12d %15ld\n", entry->name(), entry->stat_call_count, entry->stat_update_count, (long int) entry->stat_total_time / (entry->stat_update_count + 1));
874      }
875      printf("Queue Pushes %15d\n", netlist().queue().m_prof_call);
876      printf("Queue Moves  %15d\n", netlist().queue().m_prof_sortmove);
877   }
878#endif
879}
880
881// ----------------------------------------------------------------------------------------
882// Model / family
883// ----------------------------------------------------------------------------------------
884
885class logic_family_std_proxy_t : public logic_family_desc_t
886{
887public:
888   logic_family_std_proxy_t() { }
889   virtual devices::nld_base_d_to_a_proxy *create_d_a_proxy(logic_output_t *proxied) const
890   {
891      return palloc(devices::nld_d_to_a_proxy(proxied));
892   }
893};
894
895logic_family_desc_t *setup_t::family_from_model(const pstring &model)
896{
897   model_map_t map;
898   model_parse(model, map);
899
900   if (setup_t::model_value_str(map, "TYPE") == "TTL")
901      return netlist_family_TTL;
902   if (setup_t::model_value_str(map, "TYPE") == "CD4XXX")
903      return netlist_family_CD4XXX;
904
905   logic_family_std_proxy_t *ret = palloc(logic_family_std_proxy_t);
906
907   ret->m_low_thresh_V = setup_t::model_value(map, "IVL");
908   ret->m_high_thresh_V = setup_t::model_value(map, "IVH");
909   ret->m_low_V = setup_t::model_value(map, "OVL");
910   ret->m_high_V = setup_t::model_value(map, "OVH");
911   ret->m_R_low = setup_t::model_value(map, "ORL");
912   ret->m_R_high = setup_t::model_value(map, "ORH");
913
914   return ret;
915}
916
917static pstring model_string(model_map_t &map)
918{
919   pstring ret = map["COREMODEL"] + "(";
920   for (unsigned i=0; i<map.size(); i++)
921      ret = ret + map.key_at(i) + "=" + map.value_at(i) + " ";
922
923   return ret + ")";
924}
925
926
927void setup_t::model_parse(const pstring &model_in, model_map_t &map)
928{
929   pstring model = model_in;
930   int pos = 0;
931   pstring key;
932
933   while (true)
934   {
935      pos = model.find("(");
936      if (pos >= 0) break;
937
938      key = model.ucase();
939      if (!m_models.contains(key))
940         log().fatal("Model {1} not found\n", model);
941      model = m_models[key];
942   }
943   pstring xmodel = model.left(pos);
944
945   if (xmodel.equals("_"))
946      map["COREMODEL"] = key;
947   else
948   {
949      if (m_models.contains(xmodel))
950         model_parse(xmodel, map);
951      else
952         log().fatal("Model doesn't exist {1}\n", xmodel);
953   }
954
955   pstring remainder=model.substr(pos+1).trim();
956   if (!remainder.endsWith(")"))
957      log().fatal("Model error {1}\n", model);
958   remainder = remainder.left(remainder.len() - 1);
959
960   pstring_list_t pairs(remainder," ", true);
961   for (unsigned i=0; i<pairs.size(); i++)
962   {
963      int pose = pairs[i].find("=");
964      if (pose < 0)
965         log().fatal("Model error on pair {1}\n", model);
966      map[pairs[i].left(pose).ucase()] = pairs[i].substr(pose+1);
967   }
968}
969
970const pstring setup_t::model_value_str(model_map_t &map, const pstring &entity)
971{
972   pstring ret;
973
974   if (entity != entity.ucase())
975      log().fatal("model parameters should be uppercase:{1} {2}\n", entity, model_string(map));
976   if (!map.contains(entity))
977      log().fatal("Entity {1} not found in model {2}\n", entity, model_string(map));
978   else
979      ret = map[entity];
980
981   return ret;
982}
983
984nl_double setup_t::model_value(model_map_t &map, const pstring &entity)
985{
986   pstring tmp = model_value_str(map, entity);
987
988   nl_double factor = NL_FCONST(1.0);
989   pstring numfac = tmp.right(1);
990   switch (numfac.code_at(0))
991   {
992      case 'M': factor = 1e6; break;
993      case 'k': factor = 1e3; break;
994      case 'm': factor = 1e-3; break;
995      case 'u': factor = 1e-6; break;
996      case 'n': factor = 1e-9; break;
997      case 'p': factor = 1e-12; break;
998      case 'f': factor = 1e-15; break;
999      case 'a': factor = 1e-18; break;
1000      default:
1001         if (numfac < "0" || numfac > "9")
1002            fatalerror_e(pfmt("Unknown number factor <{1}> in: {2}")(numfac)(entity));
1003   }
1004   if (factor != NL_FCONST(1.0))
1005      tmp = tmp.left(tmp.len() - 1);
1006   return tmp.as_double() * factor;
1007}
1008
1009// ----------------------------------------------------------------------------------------
1010// Sources
1011// ----------------------------------------------------------------------------------------
1012
1013void setup_t::include(const pstring &netlist_name)
1014{
1015   for (std::size_t i=0; i < m_sources.size(); i++)
1016   {
1017      if (m_sources[i]->parse(*this, netlist_name))
1018         return;
1019   }
1020   log().fatal("unable to find {1} in source collection", netlist_name);
1021}
1022
1023// ----------------------------------------------------------------------------------------
1024// base sources
1025// ----------------------------------------------------------------------------------------
1026
1027bool source_string_t::parse(setup_t &setup, const pstring &name)
1028{
1029   pimemstream istrm(m_str.cstr(), m_str.len());
1030   pomemstream ostrm;
1031
1032   pimemstream istrm2(ppreprocessor().process(istrm, ostrm));
1033   return parser_t(istrm2, setup).parse(name);
1034}
1035
1036bool source_mem_t::parse(setup_t &setup, const pstring &name)
1037{
1038   pimemstream istrm(m_str.cstr(), m_str.len());
1039   pomemstream ostrm;
1040
1041   pimemstream istrm2(ppreprocessor().process(istrm, ostrm));
1042   return parser_t(istrm2, setup).parse(name);
1043}
1044
1045bool source_file_t::parse(setup_t &setup, const pstring &name)
1046{
1047   pifilestream istrm(m_filename);
1048   pomemstream ostrm;
1049
1050   pimemstream istrm2(ppreprocessor().process(istrm, ostrm));
1051   return parser_t(istrm2, setup).parse(name);
1052}
1053
1054}
trunk/src/lib/netlist/nl_setup.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nlsetup.h
5 *
6 */
7
8#ifndef NLSETUP_H_
9#define NLSETUP_H_
10
11#include "nl_base.h"
12
13//============================================================
14//  MACROS / inline netlist definitions
15//============================================================
16
17#define NET_STR(_x) # _x
18
19#define NET_MODEL(_model)                                                           \
20   setup.register_model(_model);
21
22#define ALIAS(_alias, _name)                                                        \
23   setup.register_alias(# _alias, # _name);
24
25#define DIPPINS(_pin1, ...)                                                          \
26      setup.register_dippins_arr( #_pin1 ", " # __VA_ARGS__);
27
28/* to be used to reference new library truthtable devices */
29#define NET_REGISTER_DEV(_type, _name)                                            \
30      setup.register_dev(# _type, # _name);
31
32#define NET_REGISTER_SIGNAL(_type, _name)                                           \
33      NET_REGISTER_DEV(_type ## _ ## sig, _name)
34
35#define NET_CONNECT(_name, _input, _output)                                         \
36      setup.register_link(# _name "." # _input, # _output);
37
38#define NET_C(_term1, ...)                                                          \
39      setup.register_link_arr( #_term1 ", " # __VA_ARGS__);
40
41#define PARAM(_name, _val)                                                          \
42      setup.register_param(# _name, _val);
43
44#define NETDEV_PARAMI(_name, _param, _val)                                          \
45      setup.register_param(# _name "." # _param, _val);
46
47#define NETLIST_NAME(_name) netlist ## _ ## _name
48
49#define NETLIST_EXTERNAL(_name)                                                \
50      ATTR_COLD void NETLIST_NAME(_name)(netlist::setup_t &setup);
51
52#define NETLIST_START(_name)                                                   \
53ATTR_COLD void NETLIST_NAME(_name)(netlist::setup_t &setup)                    \
54{
55#define NETLIST_END()  }
56
57#define LOCAL_SOURCE(_name)                                                    \
58      setup.register_source(palloc(netlist::source_proc_t(# _name, &NETLIST_NAME(_name))));
59
60#define LOCAL_LIB_ENTRY(_name)                                                 \
61      LOCAL_SOURCE(_name)                                                    \
62      setup.register_lib_entry(# _name);
63
64#define INCLUDE(_name)                                                         \
65      setup.include(# _name);
66
67#define SUBMODEL(_model, _name)                                                \
68      setup.namespace_push(# _name);                                         \
69      NETLIST_NAME(_model)(setup);                                           \
70      setup.namespace_pop();
71
72// ----------------------------------------------------------------------------------------
73// netlist_setup_t
74// ----------------------------------------------------------------------------------------
75
76namespace netlist
77{
78   // Forward definition so we keep nl_factory.h out of the public
79   class factory_list_t;
80
81
82   class setup_t
83   {
84      P_PREVENT_COPYING(setup_t)
85   public:
86
87      // ----------------------------------------------------------------------------------------
88      // A Generic netlist sources implementation
89      // ----------------------------------------------------------------------------------------
90
91      class source_t
92      {
93      public:
94         typedef plist_t<source_t *> list_t;
95
96         source_t()
97         {}
98
99         virtual ~source_t() { }
100
101         virtual bool parse(setup_t &setup, const pstring &name) = 0;
102      private:
103      };
104
105      struct link_t
106      {
107         link_t() { }
108         link_t(void *) { }
109         // Copy constructor
110         link_t(const link_t &from)
111         {
112            e1 = from.e1;
113            e2 = from.e2;
114         }
115
116         link_t(const pstring &ae1, const pstring &ae2)
117         {
118            e1 = ae1;
119            e2 = ae2;
120         }
121         pstring e1;
122         pstring e2;
123
124         bool operator==(const link_t &rhs) const { return (e1 == rhs.e1) && (e2 == rhs.e2); }
125         link_t &operator=(const link_t &rhs) { e1 = rhs.e1; e2 = rhs.e2; return *this; }
126
127         const pstring &name() const { return e1; }
128      };
129
130      setup_t(netlist_t *netlist);
131      ~setup_t();
132
133      void init();
134
135      netlist_t &netlist() { return *m_netlist; }
136      const netlist_t &netlist() const { return *m_netlist; }
137
138      pstring build_fqn(const pstring &obj_name) const;
139
140      device_t *register_dev(device_t *dev, const pstring &name);
141      device_t *register_dev(const pstring &classname, const pstring &name);
142      void remove_dev(const pstring &name);
143
144      void register_lib_entry(const pstring &name);
145
146      void register_model(const pstring &model_in);
147      void register_alias(const pstring &alias, const pstring &out);
148      void register_dippins_arr(const pstring &terms);
149
150      void register_alias_nofqn(const pstring &alias, const pstring &out);
151
152      void register_link_arr(const pstring &terms);
153      void register_link_fqn(const pstring &sin, const pstring &sout);
154      void register_link(const pstring &sin, const pstring &sout);
155
156      void register_param(const pstring &param, const pstring &value);
157      void register_param(const pstring &param, const double value);
158
159      void register_frontier(const pstring attach, const double r_IN, const double r_OUT);
160      void remove_connections(const pstring attach);
161
162      void register_object(device_t &dev, const pstring &name, object_t &obj);
163      bool connect(core_terminal_t &t1, core_terminal_t &t2);
164
165      core_terminal_t *find_terminal(const pstring &outname_in, bool required = true);
166      core_terminal_t *find_terminal(const pstring &outname_in, object_t::type_t atype, bool required = true);
167
168      param_t *find_param(const pstring &param_in, bool required = true);
169
170      void start_devices();
171      void resolve_inputs();
172
173      /* handle namespace */
174
175      void namespace_push(const pstring &aname);
176      void namespace_pop();
177
178      /* parse a source */
179
180      void include(const pstring &netlist_name);
181
182      /* register a source */
183
184      void register_source(source_t *src) { m_sources.add(src); }
185
186      factory_list_t &factory() { return *m_factory; }
187      const factory_list_t &factory() const { return *m_factory; }
188
189      bool is_library_item(const pstring &name) const { return m_lib.contains(name); }
190
191      void print_stats() const;
192
193      /* model / family related */
194
195      logic_family_desc_t *family_from_model(const pstring &model);
196      const pstring model_value_str(model_map_t &map, const pstring &entity);
197      nl_double model_value(model_map_t &map, const pstring &entity);
198
199      void model_parse(const pstring &model, model_map_t &map);
200
201      plog_base<NL_DEBUG> &log() { return netlist().log(); }
202      const plog_base<NL_DEBUG> &log() const { return netlist().log(); }
203
204   protected:
205
206   private:
207
208      void connect_terminals(core_terminal_t &in, core_terminal_t &out);
209      void connect_input_output(core_terminal_t &in, core_terminal_t &out);
210      void connect_terminal_output(terminal_t &in, core_terminal_t &out);
211      void connect_terminal_input(terminal_t &term, core_terminal_t &inp);
212      bool connect_input_input(core_terminal_t &t1, core_terminal_t &t2);
213
214      // helpers
215      pstring objtype_as_astr(object_t &in) const;
216
217      const pstring resolve_alias(const pstring &name) const;
218      devices::nld_base_proxy *get_d_a_proxy(core_terminal_t &out);
219
220      netlist_t *m_netlist;
221
222      phashmap_t<pstring, pstring> m_alias;
223      phashmap_t<pstring, param_t *>  m_params;
224      phashmap_t<pstring, pstring> m_params_temp;
225      phashmap_t<pstring, core_terminal_t *> m_terminals;
226
227      plist_t<link_t> m_links;
228
229      factory_list_t *m_factory;
230
231      phashmap_t<pstring, pstring> m_models;
232
233      int m_proxy_cnt;
234
235      pstack_t<pstring> m_stack;
236      source_t::list_t m_sources;
237      plist_t<pstring> m_lib;
238
239   };
240
241   // ----------------------------------------------------------------------------------------
242   // base sources
243   // ----------------------------------------------------------------------------------------
244
245
246   class source_string_t : public setup_t::source_t
247   {
248   public:
249
250      source_string_t(const pstring &source)
251      : setup_t::source_t(), m_str(source)
252      {
253      }
254
255      bool parse(setup_t &setup, const pstring &name);
256
257   private:
258      pstring m_str;
259   };
260
261   class source_file_t : public setup_t::source_t
262   {
263   public:
264
265      source_file_t(const pstring &filename)
266      : setup_t::source_t(), m_filename(filename)
267      {
268      }
269
270      bool parse(setup_t &setup, const pstring &name);
271
272   private:
273      pstring m_filename;
274   };
275
276   class source_mem_t : public setup_t::source_t
277   {
278   public:
279      source_mem_t(const char *mem)
280      : setup_t::source_t(), m_str(mem)
281      {
282      }
283
284      bool parse(setup_t &setup, const pstring &name);
285
286   private:
287      pstring m_str;
288   };
289
290   class source_proc_t : public setup_t::source_t
291   {
292   public:
293      source_proc_t(pstring name, void (*setup_func)(setup_t &))
294      : setup_t::source_t(),
295         m_setup_func(setup_func),
296         m_setup_func_name(name)
297      {
298      }
299
300      bool parse(setup_t &setup, const pstring &name)
301      {
302         if (name == m_setup_func_name)
303         {
304            m_setup_func(setup);
305            return true;
306         }
307         else
308            return false;
309      }
310   private:
311      void (*m_setup_func)(setup_t &);
312      pstring m_setup_func_name;
313   };
314
315}
316
317
318#endif /* NLSETUP_H_ */
trunk/src/lib/netlist/nl_time.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nltime.h
5 */
6
7#ifndef NLTIME_H_
8#define NLTIME_H_
9
10#include "nl_config.h"
11#include "plib/pstate.h"
12
13//============================================================
14//  MACROS
15//============================================================
16
17#define NLTIME_FROM_NS(_t)  netlist_time::from_nsec(_t)
18#define NLTIME_FROM_US(_t)  netlist_time::from_usec(_t)
19#define NLTIME_FROM_MS(_t)  netlist_time::from_msec(_t)
20#define NLTIME_IMMEDIATE    netlist_time::from_nsec(1)
21
22// ----------------------------------------------------------------------------------------
23// net_list_time
24// ----------------------------------------------------------------------------------------
25
26#undef ATTR_HOT
27#define ATTR_HOT
28
29namespace netlist
30{
31   struct netlist_time
32   {
33   public:
34
35#if (PHAS_INT128)
36      typedef UINT128 INTERNALTYPE;
37      static const pstate_data_type_e STATETYPE = DT_INT128;
38#else
39      typedef UINT64 INTERNALTYPE;
40      static const pstate_data_type_e STATETYPE = DT_INT64;
41#endif
42      static const INTERNALTYPE RESOLUTION = NETLIST_INTERNAL_RES;
43
44      ATTR_HOT netlist_time() : m_time(0) {}
45      ATTR_HOT netlist_time(const netlist_time &rhs) : m_time(rhs.m_time) {}
46
47      ATTR_HOT friend const netlist_time operator-(const netlist_time &left, const netlist_time &right);
48      ATTR_HOT friend const netlist_time operator+(const netlist_time &left, const netlist_time &right);
49      ATTR_HOT friend const netlist_time operator*(const netlist_time &left, const UINT64 factor);
50      ATTR_HOT friend UINT64 operator/(const netlist_time &left, const netlist_time &right);
51      ATTR_HOT friend bool operator>(const netlist_time &left, const netlist_time &right);
52      ATTR_HOT friend bool operator<(const netlist_time &left, const netlist_time &right);
53      ATTR_HOT friend bool operator>=(const netlist_time &left, const netlist_time &right);
54      ATTR_HOT friend bool operator<=(const netlist_time &left, const netlist_time &right);
55      ATTR_HOT friend bool operator!=(const netlist_time &left, const netlist_time &right);
56
57      ATTR_HOT const netlist_time &operator=(const netlist_time &right) { m_time = right.m_time; return *this; }
58
59      ATTR_HOT const netlist_time &operator+=(const netlist_time &right) { m_time += right.m_time; return *this; }
60
61      ATTR_HOT INTERNALTYPE as_raw() const { return m_time; }
62      ATTR_HOT double as_double() const { return (double) m_time / (double) RESOLUTION; }
63
64      // for save states ....
65      ATTR_HOT INTERNALTYPE *get_internaltype_ptr() { return &m_time; }
66
67      ATTR_HOT static const netlist_time from_nsec(const INTERNALTYPE ns) { return netlist_time(ns * (RESOLUTION / U64(1000000000))); }
68      ATTR_HOT static const netlist_time from_usec(const INTERNALTYPE us) { return netlist_time(us * (RESOLUTION / U64(1000000))); }
69      ATTR_HOT static const netlist_time from_msec(const INTERNALTYPE ms) { return netlist_time(ms * (RESOLUTION / U64(1000))); }
70      ATTR_HOT static const netlist_time from_hz(const INTERNALTYPE hz) { return netlist_time(RESOLUTION / hz); }
71      ATTR_HOT static const netlist_time from_double(const double t) { return netlist_time((INTERNALTYPE) ( t * (double) RESOLUTION)); }
72      ATTR_HOT static const netlist_time from_raw(const INTERNALTYPE raw) { return netlist_time(raw); }
73
74      static const netlist_time zero;
75
76   protected:
77
78      ATTR_HOT netlist_time(const INTERNALTYPE val) : m_time(val) {}
79
80   private:
81      INTERNALTYPE m_time;
82   };
83
84   ATTR_HOT inline const netlist_time operator-(const netlist_time &left, const netlist_time &right)
85   {
86      return netlist_time(left.m_time - right.m_time);
87   }
88
89   ATTR_HOT inline const netlist_time operator*(const netlist_time &left, const UINT64 factor)
90   {
91      return netlist_time(left.m_time * factor);
92   }
93
94   ATTR_HOT inline UINT64 operator/(const netlist_time &left, const netlist_time &right)
95   {
96      return left.m_time / right.m_time;
97   }
98
99   ATTR_HOT inline const netlist_time operator+(const netlist_time &left, const netlist_time &right)
100   {
101      return netlist_time(left.m_time + right.m_time);
102   }
103
104   ATTR_HOT inline bool operator<(const netlist_time &left, const netlist_time &right)
105   {
106      return (left.m_time < right.m_time);
107   }
108
109   ATTR_HOT inline bool operator>(const netlist_time &left, const netlist_time &right)
110   {
111      return (left.m_time > right.m_time);
112   }
113
114   ATTR_HOT inline bool operator<=(const netlist_time &left, const netlist_time &right)
115   {
116      return (left.m_time <= right.m_time);
117   }
118
119   ATTR_HOT inline bool operator>=(const netlist_time &left, const netlist_time &right)
120   {
121      return (left.m_time >= right.m_time);
122   }
123
124   ATTR_HOT inline bool operator!=(const netlist_time &left, const netlist_time &right)
125   {
126      return (left.m_time != right.m_time);
127   }
128
129}
130
131template<> ATTR_COLD inline void pstate_manager_t::save_item(netlist::netlist_time &nlt, const void *owner, const pstring &stname)
132{
133   save_state_ptr(stname, netlist::netlist_time::STATETYPE, owner, sizeof(netlist::netlist_time::INTERNALTYPE), 1, nlt.get_internaltype_ptr(), false);
134}
135
136
137#endif /* NLTIME_H_ */
trunk/src/lib/netlist/nl_util.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nl_util.h
5 *
6 */
7
8#ifndef NL_UTIL_H_
9#define NL_UTIL_H_
10
11#include <cmath>
12#include <cstring>
13#include <cstdlib>
14
15#include "plib/pstring.h"
16#include "plib/plists.h"
17
18class nl_util
19{
20// this is purely static
21private:
22   nl_util() {};
23
24public:
25
26
27   static const pstring environment(const pstring &var, const pstring &default_val = "")
28   {
29      if (getenv(var.cstr()) == NULL)
30         return default_val;
31      else
32         return pstring(getenv(var.cstr()));
33   }
34};
35
36class nl_math
37{
38// this is purely static
39private:
40   nl_math() {};
41
42public:
43   ATTR_HOT inline static float exp(const float x) { return std::exp(x); }
44   ATTR_HOT inline static double abs(const double x) { return std::abs(x); }
45   ATTR_HOT inline static float abs(const float x) { return std::abs(x); }
46   ATTR_HOT inline static double log(const double x) { return std::log(x); }
47   ATTR_HOT inline static float log(const float x) { return std::log(x); }
48#if defined(_MSC_VER) && _MSC_VER < 1800
49   ATTR_HOT inline static double e_log1p(const double x) { return nl_math::log(1.0 + x); }
50   ATTR_HOT inline static float e_log1p(const float x) { return nl_math::log(1.0 + x); }
51#else
52   ATTR_HOT inline static double e_log1p(const double x) { return log1p(x); }
53   ATTR_HOT inline static float e_log1p(const float x) { return log1pf(x); }
54#endif
55   ATTR_HOT inline static double sqrt(const double x) { return std::sqrt(x); }
56   ATTR_HOT inline static float sqrt(const float x) { return std::sqrt(x); }
57
58   // this one has an accuracy of better than 5%. That's enough for our purpose
59   // add c3 and it'll be better than 1%
60
61#if 0
62   inline static double fastexp_h(const double x)
63   {
64      /* static */ const double ln2r = 1.442695040888963387;
65      /* static */ const double ln2  = 0.693147180559945286;
66      /* static */ const double c3   = 0.166666666666666667;
67      /* static */ const double c4   = 1.0 / 24.0;
68      /* static */ const double c5   = 1.0 / 120.0;
69
70      const double y = x * ln2r;
71      const UINT32 t = y;
72      const double z = (x - ln2 * (double) t);
73      const double e = (1.0 + z * (1.0 + z * (0.5 + z * (c3  + z * (c4 + c5*z)))));
74
75      if (t < 63)
76         //return (double)((UINT64) 1 <<  t)*(1.0 + z + 0.5 * zz + c3 * zzz+c4*zzzz+c5*zzzzz);
77         return (double)((UINT64) 1 <<  t) * e;
78      else
79         return pow(2.0, t)*e;
80   }
81
82   ATTR_HOT inline static double exp(const double x)
83   {
84      if (x<0)
85         return 1.0 / fastexp_h(-x);
86      else
87         return fastexp_h(x);
88   }
89#else
90   ATTR_HOT inline static double exp(const double x)  { return std::exp(x); }
91#endif
92
93};
94
95#endif /* NL_UTIL_H_ */
trunk/src/lib/netlist/plib/palloc.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * palloc.c
5 *
6 */
7
8#include <cstdio>
9
10#include "pconfig.h"
11#include "palloc.h"
12//============================================================
13//  Exceptions
14//============================================================
15
16pexception::pexception(const pstring &text)
17{
18   m_text = text;
19   fprintf(stderr, "%s\n", m_text.cstr());
20}
21
22#if (PSTANDALONE)
23#include <stdlib.h>
24#include <xmmintrin.h>
25
26class pmemory_pool
27{
28public:
29   pmemory_pool() {}
30};
31
32static pmemory_pool sppool;
33
34pmemory_pool *ppool = &sppool;
35
36void* operator new(std::size_t size, pmemory_pool *pool) throw (std::bad_alloc)
37{
38   //printf("here new\n");
39   return palloc_raw(size);;
40}
41
42void operator delete(void *ptr, pmemory_pool *pool)
43{
44   //printf("here delete\n");
45   if (ptr != NULL)
46      pfree_raw(ptr);
47}
48
49void *palloc_raw(const size_t size)
50{
51   return _mm_malloc(size, 64);
52}
53
54void pfree_raw(void *p)
55{
56   _mm_free(p);
57}
58#endif
trunk/src/lib/netlist/plib/palloc.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * palloc.h
5 *
6 */
7
8#ifndef PALLOC_H_
9#define PALLOC_H_
10
11#include <exception>
12
13#include "pconfig.h"
14#include "pstring.h"
15
16//============================================================
17//  exception base
18//============================================================
19
20class pexception : public std::exception
21{
22public:
23   pexception(const pstring &text);
24   virtual ~pexception() throw() {}
25
26   const pstring &text() { return m_text; }
27
28private:
29   pstring m_text;
30};
31
32//============================================================
33//  Memory allocation
34//============================================================
35
36#if (PSTANDALONE)
37#include <cstddef>
38#include <new>
39
40#if defined(__GNUC__) && (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))
41#if !defined(__ppc__) && !defined (__PPC__) && !defined(__ppc64__) && !defined(__PPC64__)
42#define ATTR_ALIGN __attribute__ ((aligned(64)))
43#else
44#define ATTR_ALIGN
45#endif
46#else
47#define ATTR_ALIGN
48#endif
49
50class pmemory_pool;
51
52extern pmemory_pool *ppool;
53
54void *palloc_raw(const size_t size);
55void pfree_raw(void *p);
56
57void* operator new(std::size_t size, pmemory_pool *pool) throw (std::bad_alloc);
58
59void operator delete(void *ptr, pmemory_pool *pool);
60
61template<typename T>
62inline void pfree_t(T *p)
63{
64   p->~T();
65   pfree_raw(p);
66}
67
68template <typename T>
69inline T *palloc_array_t(size_t N)
70{
71   char *buf = reinterpret_cast<char *>(palloc_raw(N * sizeof(T) + 64*2));
72   size_t *s = reinterpret_cast<size_t *>(buf);
73   *s = N;
74   buf += 64;
75   T *p = reinterpret_cast<T *>(buf);
76   for (size_t i = 0; i < N; i++)
77      new(reinterpret_cast<void *>(&p[i])) T();
78   return p;
79}
80
81template <typename T>
82inline void pfree_array_t(T *p)
83{
84   char *buf = reinterpret_cast<char *>(p);
85   buf -= 64;
86   size_t *s = reinterpret_cast<size_t *>(buf);
87   size_t N = *s;
88   while (N > 0)
89   {
90         p->~T();
91         p++;
92         N--;
93   }
94   pfree_raw(s);
95}
96
97#define palloc(T)             new(ppool) T
98#define pfree(_ptr)           pfree_t(_ptr)
99
100#if 1
101#define palloc_array(T, N)    palloc_array_t<T>(N)
102#define pfree_array(_ptr)     pfree_array_t(_ptr)
103#else
104#define palloc_array(T, N)    new T[N]
105#define pfree_array(_ptr)     delete[] _ptr
106#endif
107#else
108#include "corealloc.h"
109
110#define ATTR_ALIGN
111
112#define palloc(T)             global_alloc(T)
113#define pfree(_ptr)           global_free(_ptr)
114
115#define palloc_array(T, N)    global_alloc_array(T, N)
116#define pfree_array(_ptr)     global_free_array(_ptr)
117
118#endif
119
120#endif /* NLCONFIG_H_ */
trunk/src/lib/netlist/plib/pconfig.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * pconfig.h
5 *
6 */
7
8// for now, make buggy GCC/Mingw STFU about I64FMT
9#if (defined(__MINGW32__) && (__GNUC__ >= 5))
10#pragma GCC diagnostic push
11#pragma GCC diagnostic ignored "-Wformat"
12#pragma GCC diagnostic ignored "-Wformat-extra-args"
13#endif
14
15#ifndef PCONFIG_H_
16#define PCONFIG_H_
17
18#ifndef PSTANDALONE
19   #define PSTANDALONE (0)
20#endif
21
22//#define PHAS_INT128 (0)
23
24#ifndef PHAS_INT128
25#define PHAS_INT128 (0)
26#endif
27
28#if (PHAS_INT128)
29typedef __uint128_t UINT128;
30typedef __int128_t INT128;
31#endif
32
33
34#if !(PSTANDALONE)
35#include "osdcore.h"
36#include "eminline.h"
37
38#ifndef assert
39#define assert(x) do {} while (0)
40#endif
41
42#include "delegate.h"
43
44#else
45#include <stdint.h>
46#endif
47#include <cstddef>
48
49
50//============================================================
51//  Standard defines
52//============================================================
53
54// prevent implicit copying
55#define P_PREVENT_COPYING(_name)                \
56   private:                                    \
57      _name(const _name &);                   \
58      _name &operator=(const _name &);
59
60//============================================================
61//  Compiling standalone
62//============================================================
63
64#if !(PSTANDALONE)
65
66/* use MAME */
67#if (USE_DELEGATE_TYPE == DELEGATE_TYPE_INTERNAL)
68#define PHAS_PMF_INTERNAL 1
69#else
70#define PHAS_PMF_INTERNAL 0
71#endif
72
73#else
74
75/* determine PMF approach */
76
77#if defined(__GNUC__)
78   /* does not work in versions over 4.7.x of 32bit MINGW  */
79   #if defined(__MINGW32__) && !defined(__x86_64) && defined(__i386__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)))
80      #define PHAS_PMF_INTERNAL 1
81      #define MEMBER_ABI __thiscall
82   #elif defined(EMSCRIPTEN)
83      #define PHAS_PMF_INTERNAL 0
84   #elif defined(__arm__) || defined(__ARMEL__)
85      #define PHAS_PMF_INTERNAL 0
86   #else
87      #define PHAS_PMF_INTERNAL 1
88   #endif
89#else
90#define USE_DELEGATE_TYPE PHAS_PMF_INTERNAL 0
91#endif
92
93#ifndef MEMBER_ABI
94   #define MEMBER_ABI
95#endif
96
97/* not supported in GCC prior to 4.4.x */
98/* ATTR_HOT and ATTR_COLD cause performance degration in 5.1 */
99//#define ATTR_HOT
100//#define ATTR_COLD
101#define ATTR_HOT               __attribute__((hot))
102#define ATTR_COLD              __attribute__((cold))
103
104#define RESTRICT                __restrict__
105#define EXPECTED(x)     (x)
106#define UNEXPECTED(x)   (x)
107#define ATTR_PRINTF(x,y)        __attribute__((format(printf, x, y)))
108#define ATTR_UNUSED             __attribute__((__unused__))
109
110/* 8-bit values */
111typedef unsigned char                       UINT8;
112typedef signed char                         INT8;
113
114/* 16-bit values */
115typedef unsigned short                      UINT16;
116typedef signed short                        INT16;
117
118/* 32-bit values */
119#ifndef _WINDOWS_H
120typedef unsigned int                        UINT32;
121typedef signed int                          INT32;
122#endif
123
124/* 64-bit values */
125#ifndef _WINDOWS_H
126#ifdef _MSC_VER
127typedef signed __int64                      INT64;
128typedef unsigned __int64                    UINT64;
129#else
130typedef uint64_t    UINT64;
131typedef int64_t      INT64;
132#endif
133#endif
134
135/* U64 and S64 are used to wrap long integer constants. */
136#if defined(__GNUC__) || defined(_MSC_VER)
137#define U64(val) val##ULL
138#define S64(val) val##LL
139#else
140#define U64(val) val
141#define S64(val) val
142#endif
143
144#endif
145
146/*
147 * The following class was derived from the MAME delegate.h code.
148 * It derives a pointer to a member function.
149 */
150
151#if (PHAS_PMF_INTERNAL)
152class pmfp
153{
154public:
155   // construct from any member function pointer
156   class generic_class;
157   typedef void (*generic_function)();
158
159   #if (PSTANDALONE)
160   typedef std::size_t FPTR;
161   #endif
162
163   template<typename _MemberFunctionType>
164   pmfp(_MemberFunctionType mfp)
165   : m_function(0), m_this_delta(0)
166   {
167      *reinterpret_cast<_MemberFunctionType *>(this) = mfp;
168   }
169
170   // binding helper
171   template<typename _FunctionType, typename _ObjectType>
172   _FunctionType update_after_bind(_ObjectType *object)
173   {
174      return reinterpret_cast<_FunctionType>(
175            convert_to_generic(reinterpret_cast<generic_class *>(object)));
176   }
177   template<typename _FunctionType, typename _MemberFunctionType, typename _ObjectType>
178   static _FunctionType get_mfp(_MemberFunctionType mfp, _ObjectType *object)
179   {
180      pmfp mfpo(mfp);
181      return mfpo.update_after_bind<_FunctionType>(object);
182   }
183
184private:
185   // extract the generic function and adjust the object pointer
186   generic_function convert_to_generic(generic_class * object) const
187   {
188      // apply the "this" delta to the object first
189      generic_class * o_p_delta = reinterpret_cast<generic_class *>(reinterpret_cast<UINT8 *>(object) + m_this_delta);
190
191      // if the low bit of the vtable index is clear, then it is just a raw function pointer
192      if (!(m_function & 1))
193         return reinterpret_cast<generic_function>(m_function);
194
195      // otherwise, it is the byte index into the vtable where the actual function lives
196      UINT8 *vtable_base = *reinterpret_cast<UINT8 **>(o_p_delta);
197      return *reinterpret_cast<generic_function *>(vtable_base + m_function - 1);
198   }
199
200   // actual state
201   FPTR                    m_function;         // first item can be one of two things:
202                                    //    if even, it's a pointer to the function
203                                    //    if odd, it's the byte offset into the vtable
204   int                     m_this_delta;       // delta to apply to the 'this' pointer
205};
206#endif
207
208#endif /* PCONFIG_H_ */
209
210#if (defined(__MINGW32__) && (__GNUC__ >= 5))
211#pragma GCC diagnostic pop
212#endif
trunk/src/lib/netlist/plib/plists.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * plists.h
5 *
6 */
7
8#pragma once
9
10#ifndef PLISTS_H_
11#define PLISTS_H_
12
13#include <cstring>
14#include <algorithm>
15#include <cmath>
16
17#include "palloc.h"
18#include "pstring.h"
19
20// ----------------------------------------------------------------------------------------
21// parray_t: dynamic array
22// ----------------------------------------------------------------------------------------
23
24template <class _ListClass>
25class parray_t
26{
27public:
28
29   ATTR_COLD parray_t(std::size_t numElements)
30   : m_list(0), m_capacity(0)
31   {
32      set_capacity(numElements);
33   }
34
35   ATTR_COLD parray_t(const parray_t &rhs)
36   : m_list(0), m_capacity(0)
37   {
38      set_capacity(rhs.size());
39      for (std::size_t i=0; i<m_capacity; i++)
40         m_list[i] = rhs[i];
41   }
42
43   ATTR_COLD parray_t &operator=(const parray_t &rhs)
44   {
45      set_capacity(rhs.size());
46      for (std::size_t i=0; i<m_capacity; i++)
47         m_list[i] = rhs[i];
48      return *this;
49   }
50
51   ~parray_t()
52   {
53      if (m_list != NULL)
54         pfree_array(m_list);
55      m_list = NULL;
56   }
57
58   /* using the [] operator will not allow gcc to vectorize code because
59    * basically a pointer is returned.
60    * array works around this.
61    */
62
63   ATTR_HOT  _ListClass *data() { return m_list; }
64
65   ATTR_HOT  _ListClass& operator[](std::size_t index) { return m_list[index]; }
66   ATTR_HOT  const _ListClass& operator[](std::size_t index) const { return m_list[index]; }
67
68   ATTR_HOT  std::size_t size() const { return m_capacity; }
69
70   void resize(const std::size_t new_size)
71   {
72      set_capacity(new_size);
73   }
74
75protected:
76   ATTR_COLD void set_capacity(const std::size_t new_capacity)
77   {
78      if (m_list != NULL)
79         pfree_array(m_list);
80      if (new_capacity > 0)
81         m_list = palloc_array(_ListClass, new_capacity);
82      else
83         m_list = NULL;
84      m_capacity = new_capacity;
85   }
86
87private:
88
89   _ListClass * m_list;
90   int m_capacity;
91};
92
93// ----------------------------------------------------------------------------------------
94// plist_t: a simple list
95// ----------------------------------------------------------------------------------------
96#if 0
97#include <vector>
98//#define plist_t std::vector
99template <typename _ListClass>
100class plist_t : public std::vector<_ListClass>
101{
102public:
103   plist_t() : std::vector<_ListClass>() {}
104   plist_t(const int numElements) : std::vector<_ListClass>(numElements) {}
105
106      void add(const _ListClass &elem) { this->push_back(elem); }
107   void clear_and_free()
108   {
109      for (_ListClass *i = this->data(); i < this->data() + this->size(); i++)
110      {
111         pfree(*i);
112      }
113      this->clear();
114   }
115      bool contains(const _ListClass &elem) const
116   {
117      for (const _ListClass *i = this->data(); i < this->data() + this->size(); i++)
118      {
119         if (*i == elem)
120            return true;
121      }
122      return false;
123   }
124
125      void remove(const _ListClass &elem)
126   {
127      for (int i = 0; i < this->size(); i++)
128      {
129         if (this->at(i) == elem)
130         {
131            this->erase(this->begin() + i);
132            return;
133         }
134      }
135   }
136      void remove_at(const int pos)
137   {
138      this->erase(this->begin() + pos);
139   }
140
141      int indexof(const _ListClass &elem) const
142   {
143      for (int i = 0; i < this->size(); i++)
144      {
145         if (this->at(i) == elem)
146            return i;
147      }
148      return -1;
149   }
150
151   ATTR_HOT  void swap(const int pos1, const int pos2)
152   {
153      //nl_assert((pos1>=0) && (pos1<m_count));
154      //nl_assert((pos2>=0) && (pos2<m_count));
155      _ListClass tmp = (*this)[pos1];
156      (*this)[pos1] = (*this)[pos2];
157      (*this)[pos2] =tmp;
158   }
159
160};
161
162#else
163template <typename _ListClass>
164class plist_t
165{
166public:
167
168   ATTR_COLD plist_t(const std::size_t numElements = 0)
169   {
170      m_capacity = numElements;
171      if (m_capacity == 0)
172         m_list = NULL;
173      else
174         m_list = this->alloc(m_capacity);
175      m_count = 0;
176   }
177
178   ATTR_COLD plist_t(const plist_t &rhs)
179   {
180      m_capacity = rhs.capacity();
181      if (m_capacity == 0)
182         m_list = NULL;
183      else
184         m_list = this->alloc(m_capacity);
185      m_count = 0;
186      for (std::size_t i=0; i<rhs.size(); i++)
187      {
188         this->add(rhs[i]);
189      }
190   }
191
192   ATTR_COLD plist_t &operator=(const plist_t &rhs)
193   {
194      this->clear();
195      for (std::size_t i=0; i<rhs.size(); i++)
196      {
197         this->add(rhs[i]);
198      }
199      return *this;
200   }
201
202
203   ~plist_t()
204   {
205      if (m_list != NULL)
206         this->dealloc(m_list);
207      m_list = NULL;
208   }
209
210   ATTR_HOT  _ListClass *data() { return m_list; }
211
212   ATTR_HOT  _ListClass& operator[](std::size_t index) { return *(m_list + index); }
213   ATTR_HOT  const _ListClass& operator[](std::size_t index) const { return *(m_list + index); }
214
215   ATTR_HOT  void add(const _ListClass &elem)
216   {
217      if (m_count >= m_capacity){
218         std::size_t new_size = m_capacity * 2;
219         if (new_size < 32)
220            new_size = 32;
221         set_capacity(new_size);
222      }
223
224      m_list[m_count++] = elem;
225   }
226
227   ATTR_HOT  void insert_at(const _ListClass &elem, const std::size_t index)
228   {
229      if (m_count >= m_capacity){
230         std::size_t new_size = m_capacity * 2;
231         if (new_size < 32)
232            new_size = 32;
233         set_capacity(new_size);
234      }
235      for (std::size_t i = m_count; i>index; i--)
236         m_list[i] = m_list[i-1];
237      m_list[index] = elem;
238      m_count++;
239   }
240
241   ATTR_HOT  void remove(const _ListClass &elem)
242   {
243      for (std::size_t i = 0; i < m_count; i++)
244      {
245         if (m_list[i] == elem)
246         {
247            m_count --;
248            while (i < m_count)
249            {
250               m_list[i] = m_list[i+1];
251               i++;
252            }
253            return;
254         }
255      }
256   }
257
258   ATTR_HOT  void remove_at(const std::size_t pos)
259   {
260      //nl_assert((pos>=0) && (pos<m_count));
261      m_count--;
262      for (std::size_t i = pos; i < m_count; i++)
263      {
264         m_list[i] = m_list[i+1];
265      }
266   }
267
268   ATTR_HOT  void swap(const std::size_t pos1, const std::size_t pos2)
269   {
270      //nl_assert((pos1>=0) && (pos1<m_count));
271      //nl_assert((pos2>=0) && (pos2<m_count));
272      _ListClass tmp = m_list[pos1];
273      m_list[pos1] = m_list[pos2];
274      m_list[pos2] =tmp;
275   }
276
277   ATTR_HOT  bool contains(const _ListClass &elem) const
278   {
279      for (_ListClass *i = m_list; i < m_list + m_count; i++)
280      {
281         if (*i == elem)
282            return true;
283      }
284      return false;
285   }
286
287   ATTR_HOT  int indexof(const _ListClass &elem) const
288   {
289      for (std::size_t i = 0; i < m_count; i++)
290      {
291         if (m_list[i] == elem)
292            return i;
293      }
294      return -1;
295   }
296
297   ATTR_HOT  std::size_t size() const { return m_count; }
298   ATTR_HOT  bool is_empty() const { return (m_count == 0); }
299   ATTR_HOT  void clear() { m_count = 0; }
300   ATTR_HOT  std::size_t capacity() const { return m_capacity; }
301
302   ATTR_COLD void clear_and_free()
303   {
304      for (_ListClass *i = m_list; i < m_list + m_count; i++)
305      {
306         pfree(*i);
307      }
308      clear();
309   }
310
311private:
312   ATTR_COLD void set_capacity(const std::size_t new_capacity)
313   {
314      std::size_t cnt = size();
315      if (new_capacity > 0)
316      {
317         _ListClass *m_new = this->alloc(new_capacity);
318         _ListClass *pd = m_new;
319
320         if (cnt > new_capacity)
321            cnt = new_capacity;
322         if (m_list != NULL)
323         {
324            for (_ListClass *ps = m_list; ps < m_list + cnt; ps++, pd++)
325               *pd = *ps;
326            this->dealloc(m_list);
327         }
328         m_list = m_new;
329         m_count = cnt;
330      }
331      else
332      {
333         if (m_list != NULL)
334            this->dealloc(m_list);
335         m_list = NULL;
336         m_count = 0;
337      }
338      m_capacity = new_capacity;
339   }
340
341   _ListClass *alloc(const std::size_t n)
342   {
343      return palloc_array(_ListClass, n);
344   }
345
346   void dealloc(_ListClass *p)
347   {
348      pfree_array(p);
349   }
350
351   std::size_t m_count;
352   _ListClass * m_list;
353   std::size_t m_capacity;
354};
355#endif
356
357// ----------------------------------------------------------------------------------------
358// pnamedlist_t: a simple list of elements which have a name() interface
359// ----------------------------------------------------------------------------------------
360
361template <class _ListClass>
362class pnamedlist_t : public plist_t<_ListClass>
363{
364public:
365   _ListClass find_by_name(const pstring &name) const
366   {
367      for (std::size_t i=0; i < this->size(); i++)
368         if (get_name((*this)[i]) == name)
369            return (*this)[i];
370      return _ListClass(NULL);
371   }
372
373   int index_by_name(const pstring &name) const
374   {
375      for (std::size_t i=0; i < this->size(); i++)
376         if (get_name((*this)[i]) == name)
377            return (int) i;
378      return -1;
379   }
380
381   void remove_by_name(const pstring &name)
382   {
383      plist_t<_ListClass>::remove(find_by_name(name));
384   }
385
386   bool add(_ListClass dev, bool allow_duplicate)
387   {
388      if (allow_duplicate)
389         plist_t<_ListClass>::add(dev);
390      else
391      {
392         if (!(this->find_by_name(get_name(dev)) == _ListClass(NULL)))
393            return false;
394         plist_t<_ListClass>::add(dev);
395      }
396      return true;
397   }
398
399private:
400   template <typename T> const pstring &get_name(const T *elem) const { return elem->name(); }
401   template <typename T> const pstring &get_name(T *elem) const { return elem->name(); }
402   template <typename T> const pstring &get_name(const T &elem) const { return elem.name(); }
403
404};
405
406
407// ----------------------------------------------------------------------------------------
408// pstack_t: a simple stack
409// ----------------------------------------------------------------------------------------
410
411template <class _StackClass>
412class pstack_t
413{
414public:
415
416   ATTR_COLD pstack_t(const int numElements = 128)
417   : m_list(numElements)
418   {
419   }
420
421   ATTR_COLD pstack_t(const pstack_t &rhs)
422   : m_list(rhs.m_list)
423   {
424   }
425
426   ATTR_COLD pstack_t &operator=(const pstack_t &rhs)
427   {
428      m_list = rhs.m_list;
429      return *this;
430   }
431
432
433   ~pstack_t()
434   {
435   }
436
437   ATTR_HOT  void push(const _StackClass &elem)
438   {
439      m_list.add(elem);
440   }
441
442   ATTR_HOT  _StackClass peek() const
443   {
444      return m_list[m_list.size() - 1];
445   }
446
447   ATTR_HOT  _StackClass pop()
448   {
449      _StackClass ret = peek();
450      m_list.remove_at(m_list.size() - 1);
451      return ret;
452   }
453
454   ATTR_HOT  int count() const { return m_list.size(); }
455   ATTR_HOT  bool empty() const { return (m_list.size() == 0); }
456   ATTR_HOT  void reset() { m_list.reset(); }
457   ATTR_HOT  int capacity() const { return m_list.capacity(); }
458
459private:
460   plist_t<_StackClass> m_list;
461};
462
463template <class _ListClass>
464struct plinkedlist_element_t
465{
466   plinkedlist_element_t() : m_next(NULL) {}
467   _ListClass * m_next;
468
469};
470
471// ----------------------------------------------------------------------------------------
472// plinkedlist_t: a simple linked list
473// ----------------------------------------------------------------------------------------
474
475template <class _ListClass>
476class plinkedlist_t
477{
478public:
479
480   plinkedlist_t() : m_head(NULL) {}
481
482   ATTR_HOT  void insert(const _ListClass &before, _ListClass &elem)
483   {
484      if (m_head == &before)
485      {
486         elem.m_next = m_head;
487         m_head = elem;
488      }
489      else
490      {
491         _ListClass *p = m_head;
492         while (p != NULL)
493         {
494            if (p->m_next == &before)
495            {
496               elem->m_next = &before;
497               p->m_next = &elem;
498               return;
499            }
500            p = p->m_next;
501         }
502         throw pexception("element not found");
503      }
504   }
505
506   ATTR_HOT  void insert(_ListClass &elem)
507   {
508      elem.m_next = m_head;
509      m_head = &elem;
510   }
511
512   ATTR_HOT  void add(_ListClass &elem)
513   {
514      _ListClass **p = &m_head;
515      while (*p != NULL)
516      {
517         p = &((*p)->m_next);
518      }
519      *p = &elem;
520      elem.m_next = NULL;
521   }
522
523   ATTR_HOT  void remove(const _ListClass &elem)
524   {
525      _ListClass **p = &m_head;
526      while (*p != &elem)
527      {
528         //nl_assert(*p != NULL);
529         p = &((*p)->m_next);
530      }
531      (*p) = elem.m_next;
532   }
533
534
535   ATTR_HOT static  _ListClass *next(const _ListClass &elem) { return elem.m_next; }
536   ATTR_HOT static  _ListClass *next(const _ListClass *elem) { return elem->m_next; }
537   ATTR_HOT  _ListClass *first() const { return m_head; }
538   ATTR_HOT  void clear() { m_head = NULL; }
539   ATTR_HOT  bool is_empty() const { return (m_head == NULL); }
540
541private:
542   _ListClass *m_head;
543};
544
545// ----------------------------------------------------------------------------------------
546// string list
547// ----------------------------------------------------------------------------------------
548
549class pstring_list_t : public plist_t<pstring>
550{
551public:
552   pstring_list_t() : plist_t<pstring>() { }
553
554   pstring_list_t(const pstring &str, const pstring &onstr, bool ignore_empty = false)
555   : plist_t<pstring>()
556   {
557      int p = 0;
558      int pn;
559
560      pn = str.find(onstr, p);
561      while (pn>=0)
562      {
563         pstring t = str.substr(p, pn - p);
564         if (!ignore_empty || t.len() != 0)
565            this->add(t);
566         p = pn + onstr.len();
567         pn = str.find(onstr, p);
568      }
569      if (p < (int) str.len())
570      {
571         pstring t = str.substr(p);
572         if (!ignore_empty || t.len() != 0)
573            this->add(t);
574      }
575   }
576
577   static pstring_list_t splitexpr(const pstring &str, const pstring_list_t &onstrl)
578   {
579      pstring_list_t temp;
580      pstring col = "";
581
582      unsigned i = 0;
583      while (i<str.blen())
584      {
585         int p = -1;
586         for (std::size_t j=0; j < onstrl.size(); j++)
587         {
588            if (std::memcmp(onstrl[j].cstr(), &(str.cstr()[i]), onstrl[j].blen())==0)
589            {
590               p = j;
591               break;
592            }
593         }
594         if (p>=0)
595         {
596            if (col != "")
597               temp.add(col);
598
599            col = "";
600            temp.add(onstrl[p]);
601            i += onstrl[p].blen();
602         }
603         else
604         {
605            pstring::traits::code_t c = pstring::traits::code(str.cstr() + i);
606            col += c;
607            i+=pstring::traits::codelen(c);
608         }
609      }
610      if (col != "")
611         temp.add(col);
612      return temp;
613   }
614};
615
616// ----------------------------------------------------------------------------------------
617// hashmap list
618// ----------------------------------------------------------------------------------------
619
620
621template <class C>
622struct phash_functor
623{
624   phash_functor()
625   {}
626   phash_functor(const C &v)
627   {
628      m_hash = v;
629   }
630   friend unsigned operator%(const phash_functor &lhs, const unsigned &rhs) { return lhs.m_hash % rhs; }
631   bool operator==(const phash_functor &lhs) const { return (m_hash == lhs.m_hash); }
632private:
633   unsigned m_hash;
634};
635
636template <>
637struct phash_functor<pstring>
638{
639   phash_functor()
640   {}
641   phash_functor(const pstring &v)
642   {
643      /* modified djb2 */
644      const pstring::mem_t *string = v.cstr();
645      unsigned result = 5381;
646      for (pstring::mem_t c = *string; c != 0; c = *string++)
647         result = ((result << 5) + result ) ^ (result >> (32 - 5)) ^ c;
648         //result = (result*33) ^ c;
649      m_hash = result;
650   }
651   friend unsigned operator%(const phash_functor<pstring> &lhs, const unsigned &rhs) { return lhs.m_hash % rhs; }
652   bool operator==(const phash_functor<pstring> &lhs) const { return (m_hash == lhs.m_hash); }
653private:
654   unsigned m_hash;
655};
656
657#if 0
658#if 0
659   unsigned hash(const pstring &v) const
660   {
661      /* Fowler???Noll???Vo hash - FNV-1 */
662      const char *string = v.cstr();
663      unsigned result = 2166136261;
664      for (UINT8 c = *string++; c != 0; c = *string++)
665         result = (result * 16777619) ^ c;
666         // result = (result ^ c) * 16777619; FNV 1a
667      return result;
668   }
669#else
670   unsigned hash(const pstring &v) const
671   {
672      /* jenkins one at a time algo */
673      unsigned result = 0;
674      const char *string = v.cstr();
675      while (*string)
676      {
677         result += *string;
678         string++;
679         result += (result << 10);
680         result ^= (result >> 6);
681      }
682      result += (result << 3);
683      result ^= (result >> 11);
684      result += (result << 15);
685      return result;
686   }
687#endif
688#endif
689
690template <class K, class V, class H = phash_functor<K> >
691class phashmap_t
692{
693public:
694   phashmap_t() : m_hash(37)
695   {
696      for (unsigned i=0; i<m_hash.size(); i++)
697         m_hash[i] = -1;
698   }
699
700   ~phashmap_t()
701   {
702   }
703
704   struct element_t
705   {
706      element_t() { }
707      element_t(const K &key, const H &hash, const V &value)
708      : m_key(key), m_hash(hash), m_value(value), m_next(-1)
709      {}
710      K m_key;
711      H m_hash;
712      V m_value;
713      int m_next;
714   };
715
716   void clear()
717   {
718#if 0
719      if (0)
720      {
721         unsigned cnt = 0;
722         for (unsigned i=0; i<m_hash.size(); i++)
723            if (m_hash[i] >= 0)
724               cnt++;
725         const unsigned s = m_values.size();
726         if (s>0)
727            printf("phashmap: %d elements %d hashsize, percent in overflow: %d\n", s, (unsigned) m_hash.size(),  (s - cnt) * 100 / s);
728         else
729            printf("phashmap: No elements .. \n");
730      }
731#endif
732      m_values.clear();
733      for (unsigned i=0; i<m_hash.size(); i++)
734         m_hash[i] = -1;
735   }
736
737   bool contains(const K &key) const
738   {
739      return (get_idx(key) >= 0);
740   }
741
742   int index_of(const K &key) const
743   {
744      return get_idx(key);
745   }
746
747   unsigned size() const { return m_values.size(); }
748
749   bool add(const K &key, const V &value)
750   {
751      /*
752       * we are using the Euler prime function here
753       *
754       * n * n + n + 41 | 40 >= n >=0
755       *
756       * and accept that outside we will not have a prime
757       *
758       */
759      if (m_values.size() * 3 / 2 > m_hash.size())
760      {
761         unsigned n = std::sqrt( 2 * m_hash.size());
762         n = n * n + n + 41;
763         m_hash.resize(n);
764         rebuild();
765      }
766      const H hash(key);
767      const unsigned pos = hash % m_hash.size();
768      if (m_hash[pos] == -1)
769      {
770         unsigned vpos = m_values.size();
771         m_values.add(element_t(key, hash, value));
772         m_hash[pos] = vpos;
773      }
774      else
775      {
776         int ep = m_hash[pos];
777
778         for (; ep != -1; ep = m_values[ep].m_next)
779         {
780            if (m_values[ep].m_hash == hash && m_values[ep].m_key == key )
781               return false; /* duplicate */
782         }
783         unsigned vpos = m_values.size();
784         m_values.add(element_t(key, hash, value));
785         m_values[vpos].m_next = m_hash[pos];
786         m_hash[pos] = vpos;
787      }
788      return true;
789   }
790
791   V& operator[](const K &key)
792   {
793      int p = get_idx(key);
794      if (p == -1)
795      {
796         p = m_values.size();
797         add(key, V());
798      }
799      return m_values[p].m_value;
800   }
801
802   V& value_at(const unsigned pos) { return m_values[pos].m_value; }
803   const V& value_at(const unsigned pos) const { return m_values[pos].m_value; }
804
805   V& key_at(const unsigned pos) { return m_values[pos].m_key; }
806private:
807
808   int get_idx(const K &key) const
809   {
810      H hash(key);
811      const unsigned pos = hash % m_hash.size();
812
813      for (int ep = m_hash[pos]; ep != -1; ep = m_values[ep].m_next)
814         if (m_values[ep].m_hash == hash && m_values[ep].m_key == key )
815            return ep;
816      return -1;
817   }
818
819   void rebuild()
820   {
821      for (unsigned i=0; i<m_hash.size(); i++)
822         m_hash[i] = -1;
823      for (unsigned i=0; i<m_values.size(); i++)
824      {
825         unsigned pos = m_values[i].m_hash % m_hash.size();
826         m_values[i].m_next = m_hash[pos];
827         m_hash[pos] = i;
828      }
829
830   }
831   plist_t<element_t> m_values;
832   parray_t<int> m_hash;
833};
834
835// ----------------------------------------------------------------------------------------
836// sort a list ... slow, I am lazy
837// elements must support ">" operator.
838// ----------------------------------------------------------------------------------------
839
840template<typename Class>
841static inline void psort_list(Class &sl)
842{
843   for(unsigned i = 0; i < sl.size(); i++)
844   {
845      for(unsigned j = i + 1; j < sl.size(); j++)
846         if(sl[i] > sl[j])
847            std::swap(sl[i], sl[j]);
848
849   }
850}
851
852#endif /* PLISTS_H_ */
trunk/src/lib/netlist/plib/poptions.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * poptions.h
5 *
6 */
7
8#pragma once
9
10#ifndef POPTIONS_H_
11#define POPTIONS_H_
12
13#include <cstddef>
14
15#include "pstring.h"
16#include "plists.h"
17
18/***************************************************************************
19    Options
20***************************************************************************/
21
22class poptions;
23
24class poption
25{
26public:
27   poption()
28   : m_short(""), m_long(""), m_help(""), m_has_argument(false)
29   {}
30
31   poption(pstring ashort, pstring along, pstring help, bool has_argument, poptions *parent = NULL);
32
33   virtual ~poption()
34   {
35   }
36
37   /* no_argument options will be called with "" argument */
38
39   virtual int parse(ATTR_UNUSED pstring argument) { return 0; }
40
41   pstring m_short;
42   pstring m_long;
43   pstring m_help;
44   bool m_has_argument;
45private:
46};
47
48class poption_str : public poption
49{
50public:
51   poption_str(pstring ashort, pstring along, pstring defval, pstring help, poptions *parent = NULL)
52   : poption(ashort, along, help, true, parent), m_val(defval)
53   {}
54
55   virtual int parse(pstring argument) { m_val = argument; return 0; }
56
57   pstring operator ()() { return m_val; }
58private:
59   pstring m_val;
60};
61
62class poption_str_limit : public poption
63{
64public:
65   poption_str_limit(pstring ashort, pstring along, pstring defval, pstring limit, pstring help, poptions *parent = NULL)
66   : poption(ashort, along, help, true, parent), m_val(defval), m_limit(limit, ":")
67   {}
68
69   virtual int parse(pstring argument)
70   {
71      if (m_limit.contains(argument))
72      {
73         m_val = argument;
74         return 0;
75      }
76      else
77         return 1;
78   }
79
80   pstring operator ()() { return m_val; }
81private:
82   pstring m_val;
83   pstring_list_t m_limit;
84};
85
86class poption_bool : public poption
87{
88public:
89   poption_bool(pstring ashort, pstring along, pstring help, poptions *parent = NULL)
90   : poption(ashort, along, help, false, parent), m_val(false)
91   {}
92
93   virtual int parse(ATTR_UNUSED pstring argument) { m_val = true; return 0; }
94
95   bool operator ()() { return m_val; }
96private:
97   bool m_val;
98};
99
100class poption_double : public poption
101{
102public:
103   poption_double(pstring ashort, pstring along, double defval, pstring help, poptions *parent = NULL)
104   : poption(ashort, along, help, true, parent), m_val(defval)
105   {}
106
107   virtual int parse(pstring argument)
108   {
109      bool err = false;
110      m_val = argument.as_double(&err);
111      return (err ? 1 : 0);
112   }
113
114   double operator ()() { return m_val; }
115private:
116   double m_val;
117};
118
119class poptions
120{
121public:
122
123   poptions() {}
124
125   poptions(poption *o[])
126   {
127      int i=0;
128      while (o[i] != NULL)
129      {
130         m_opts.add(o[i]);
131         i++;
132      }
133   }
134
135   ~poptions()
136   {
137      m_opts.clear();
138   }
139
140   void register_option(poption *opt)
141   {
142      m_opts.add(opt);
143   }
144
145   int parse(int argc, char *argv[])
146   {
147      m_app = argv[0];
148
149      for (int i=1; i<argc; )
150      {
151         pstring arg(argv[i]);
152         poption *opt = NULL;
153
154         if (arg.startsWith("--"))
155         {
156            opt = getopt_long(arg.substr(2));
157         }
158         else if (arg.startsWith("-"))
159         {
160            opt = getopt_short(arg.substr(1));
161         }
162         else
163            return i;
164         if (opt == NULL)
165            return i;
166         if (opt->m_has_argument)
167         {
168            i++; // FIXME: are there more arguments?
169            if (opt->parse(argv[i]) != 0)
170               return i - 1;
171         }
172         else
173            opt->parse("");
174         i++;
175      }
176      return argc;
177   }
178
179   pstring help()
180   {
181      pstring ret;
182
183      for (std::size_t i=0; i<m_opts.size(); i++ )
184      {
185         poption *opt = m_opts[i];
186         pstring line = "";
187         if (opt->m_short != "")
188            line += "  -" + opt->m_short;
189         if (opt->m_long != "")
190         {
191            if (line != "")
192               line += ", ";
193            else
194               line = "     ";
195            line += "--" + opt->m_long;
196         }
197         line = line.rpad(" ", 20).cat(opt->m_help);
198         ret = ret + line + "\n";
199      }
200      return ret;
201   }
202   pstring app() { return m_app; }
203
204private:
205
206   poption *getopt_short(pstring arg)
207   {
208      for (std::size_t i=0; i < m_opts.size(); i++)
209      {
210         if (m_opts[i]->m_short == arg)
211            return m_opts[i];
212      }
213      return NULL;
214   }
215   poption *getopt_long(pstring arg)
216   {
217      for (std::size_t i=0; i < m_opts.size(); i++)
218      {
219         if (m_opts[i]->m_long == arg)
220            return m_opts[i];
221      }
222      return NULL;
223   }
224
225   plist_t<poption *> m_opts;
226   pstring m_app;
227};
228
229poption::poption(pstring ashort, pstring along, pstring help, bool has_argument, poptions *parent)
230: m_short(ashort), m_long(along), m_help(help), m_has_argument(has_argument)
231{
232   if (parent != NULL)
233      parent->register_option(this);
234}
235
236
237#endif /* POPTIONS_H_ */
trunk/src/lib/netlist/plib/pparser.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * pparser.c
5 *
6 */
7
8#include <cstdarg>
9
10#include "pparser.h"
11
12// for now, make buggy GCC/Mingw STFU about I64FMT
13#if (defined(__MINGW32__) && (__GNUC__ >= 5))
14#pragma GCC diagnostic push
15#pragma GCC diagnostic ignored "-Wformat"
16#pragma GCC diagnostic ignored "-Wformat-extra-args"
17#endif
18
19// ----------------------------------------------------------------------------------------
20// A simple tokenizer
21// ----------------------------------------------------------------------------------------
22
23pstring ptokenizer::currentline_str()
24{
25   return m_cur_line;
26}
27
28
29void ptokenizer::skipeol()
30{
31   pstring::code_t c = getc();
32   while (c)
33   {
34      if (c == 10)
35      {
36         c = getc();
37         if (c != 13)
38            ungetc();
39         return;
40      }
41      c = getc();
42   }
43}
44
45
46pstring::code_t ptokenizer::getc()
47{
48   if (m_px >= m_cur_line.len())
49   {
50      if (m_strm.readline(m_cur_line))
51      {
52         m_cur_line += "\n";
53         m_px = 0;
54      }
55      else
56         return 0;
57   }
58   return m_cur_line.code_at(m_px++);
59}
60
61void ptokenizer::ungetc()
62{
63   m_px--;
64}
65
66void ptokenizer::require_token(const token_id_t &token_num)
67{
68   require_token(get_token(), token_num);
69}
70
71void ptokenizer::require_token(const token_t tok, const token_id_t &token_num)
72{
73   if (!tok.is(token_num))
74   {
75      error(pfmt("Expected token <{1}> got <{2}>")(m_tokens[token_num.id()])(tok.str()) );
76   }
77}
78
79pstring ptokenizer::get_string()
80{
81   token_t tok = get_token();
82   if (!tok.is_type(STRING))
83   {
84      error(pfmt("Expected a string, got <{1}>")(tok.str()) );
85   }
86   return tok.str();
87}
88
89pstring ptokenizer::get_identifier()
90{
91   token_t tok = get_token();
92   if (!tok.is_type(IDENTIFIER))
93   {
94      error(pfmt("Expected an identifier, got <{1}>")(tok.str()) );
95   }
96   return tok.str();
97}
98
99pstring ptokenizer::get_identifier_or_number()
100{
101   token_t tok = get_token();
102   if (!(tok.is_type(IDENTIFIER) || tok.is_type(NUMBER)))
103   {
104      error(pfmt("Expected an identifier, got <{1}>")(tok.str()) );
105   }
106   return tok.str();
107}
108
109double ptokenizer::get_number_double()
110{
111   token_t tok = get_token();
112   if (!tok.is_type(NUMBER))
113   {
114      error(pfmt("Expected a number, got <{1}>")(tok.str()) );
115   }
116   bool err = false;
117   double ret = tok.str().as_double(&err);
118   if (err)
119      error(pfmt("Expected a number, got <{1}>")(tok.str()) );
120   return ret;
121}
122
123long ptokenizer::get_number_long()
124{
125   token_t tok = get_token();
126   if (!tok.is_type(NUMBER))
127   {
128      error(pfmt("Expected a long int, got <{1}>")(tok.str()) );
129   }
130   bool err = false;
131   long ret = tok.str().as_long(&err);
132   if (err)
133      error(pfmt("Expected a long int, got <{1}>")(tok.str()) );
134   return ret;
135}
136
137ptokenizer::token_t ptokenizer::get_token()
138{
139   while (true)
140   {
141      token_t ret = get_token_internal();
142      if (ret.is_type(ENDOFFILE))
143         return ret;
144
145      if (ret.is(m_tok_comment_start))
146      {
147         do {
148            ret = get_token_internal();
149         } while (ret.is_not(m_tok_comment_end));
150      }
151      else if (ret.is(m_tok_line_comment))
152      {
153         skipeol();
154      }
155      else if (ret.str() == "#")
156      {
157         skipeol();
158      }
159      else
160      {
161         return ret;
162      }
163   }
164}
165
166ptokenizer::token_t ptokenizer::get_token_internal()
167{
168   /* skip ws */
169   pstring::code_t c = getc();
170   while (m_whitespace.find(c)>=0)
171   {
172      c = getc();
173      if (eof())
174      {
175         return token_t(ENDOFFILE);
176      }
177   }
178   if (m_number_chars_start.find(c)>=0)
179   {
180      /* read number while we receive number or identifier chars
181       * treat it as an identifier when there are identifier chars in it
182       *
183       */
184      token_type ret = NUMBER;
185      pstring tokstr = "";
186      while (true) {
187         if (m_identifier_chars.find(c)>=0 && m_number_chars.find(c)<0)
188            ret = IDENTIFIER;
189         else if (m_number_chars.find(c)<0)
190            break;
191         tokstr += c;
192         c = getc();
193      }
194      ungetc();
195      return token_t(ret, tokstr);
196   }
197   else if (m_identifier_chars.find(c)>=0)
198   {
199      /* read identifier till non identifier char */
200      pstring tokstr = "";
201      while (m_identifier_chars.find(c)>=0) {
202         tokstr += c;
203         c = getc();
204      }
205      ungetc();
206      token_id_t id = token_id_t(m_tokens.indexof(tokstr));
207      if (id.id() >= 0)
208         return token_t(id, tokstr);
209      else
210      {
211         return token_t(IDENTIFIER, tokstr);
212      }
213   }
214   else if (c == m_string)
215   {
216      pstring tokstr = "";
217      c = getc();
218      while (c != m_string)
219      {
220         tokstr += c;
221         c = getc();
222      }
223      return token_t(STRING, tokstr);
224   }
225   else
226   {
227      /* read identifier till first identifier char or ws */
228      pstring tokstr = "";
229      while ((m_identifier_chars.find(c)) < 0 && (m_whitespace.find(c) < 0)) {
230         tokstr += c;
231         /* expensive, check for single char tokens */
232         if (tokstr.len() == 1)
233         {
234            token_id_t id = token_id_t(m_tokens.indexof(tokstr));
235            if (id.id() >= 0)
236               return token_t(id, tokstr);
237         }
238         c = getc();
239      }
240      ungetc();
241      token_id_t id = token_id_t(m_tokens.indexof(tokstr));
242      if (id.id() >= 0)
243         return token_t(id, tokstr);
244      else
245      {
246         return token_t(UNKNOWN, tokstr);
247      }
248   }
249
250}
251
252ATTR_COLD void ptokenizer::error(const pstring &errs)
253{
254   verror("Error: " + errs, currentline_no(), currentline_str());
255   //throw error;
256}
257
258// ----------------------------------------------------------------------------------------
259// A simple preprocessor
260// ----------------------------------------------------------------------------------------
261
262ppreprocessor::ppreprocessor()
263: m_ifflag(0), m_level(0), m_lineno(0)
264{
265   m_expr_sep.add("!");
266   m_expr_sep.add("(");
267   m_expr_sep.add(")");
268   m_expr_sep.add("+");
269   m_expr_sep.add("-");
270   m_expr_sep.add("*");
271   m_expr_sep.add("/");
272   m_expr_sep.add("==");
273   m_expr_sep.add(" ");
274   m_expr_sep.add("\t");
275
276   m_defines.add("__PLIB_PREPROCESSOR__", define_t("__PLIB_PREPROCESSOR__", "1"));
277}
278
279void ppreprocessor::error(const pstring &err)
280{
281   throw pexception("PREPRO ERROR: " + err);
282}
283
284
285
286double ppreprocessor::expr(const pstring_list_t &sexpr, std::size_t &start, int prio)
287{
288   double val;
289   pstring tok=sexpr[start];
290   if (tok == "(")
291   {
292      start++;
293      val = expr(sexpr, start, /*prio*/ 0);
294      if (sexpr[start] != ")")
295         error("parsing error!");
296      start++;
297   }
298   else if (tok == "!")
299   {
300      start++;
301      val = expr(sexpr, start, 90);
302      if (val != 0)
303         val = 0;
304      else
305         val = 1;
306   }
307   else
308   {
309      tok=sexpr[start];
310      val = tok.as_double();
311      start++;
312   }
313   while (start < sexpr.size())
314   {
315      tok=sexpr[start];
316      if (tok == ")")
317      {
318         // FIXME: catch error
319         return val;
320      }
321      else if (tok == "+")
322      {
323         if (prio > 10)
324            return val;
325         start++;
326         val = val + expr(sexpr, start, 10);
327      }
328      else if (tok == "-")
329      {
330         if (prio > 10)
331            return val;
332         start++;
333         val = val - expr(sexpr, start, 10);
334      }
335      else if (tok == "*")
336      {
337         start++;
338         val = val * expr(sexpr, start, 20);
339      }
340      else if (tok == "/")
341      {
342         start++;
343         val = val / expr(sexpr, start, 20);
344      }
345      else if (tok == "==")
346      {
347         if (prio > 5)
348            return val;
349         start++;
350         val = (val == expr(sexpr, start, 5)) ? 1.0 : 0.0;
351      }
352   }
353   return val;
354}
355
356ppreprocessor::define_t *ppreprocessor::get_define(const pstring &name)
357{
358   int idx = m_defines.index_of(name);
359   if (idx >= 0)
360      return &m_defines.value_at(idx);
361   else
362      return NULL;
363}
364
365pstring ppreprocessor::replace_macros(const pstring &line)
366{
367   pstring_list_t elems = pstring_list_t::splitexpr(line, m_expr_sep);
368   pstringbuffer ret = "";
369   for (std::size_t i=0; i<elems.size(); i++)
370   {
371      define_t *def = get_define(elems[i]);
372      if (def != NULL)
373         ret.cat(def->m_replace);
374      else
375         ret.cat(elems[i]);
376   }
377   return ret;
378}
379
380static pstring catremainder(const pstring_list_t &elems, std::size_t start, pstring sep)
381{
382   pstringbuffer ret = "";
383   for (std::size_t i=start; i<elems.size(); i++)
384   {
385      ret.cat(elems[i]);
386      ret.cat(sep);
387   }
388   return ret;
389}
390
391pstring  ppreprocessor::process_line(const pstring &line)
392{
393   pstring lt = line.replace("\t"," ").trim();
394   pstringbuffer ret;
395   m_lineno++;
396   // FIXME ... revise and extend macro handling
397   if (lt.startsWith("#"))
398   {
399      pstring_list_t lti(lt, " ", true);
400      if (lti[0].equals("#if"))
401      {
402         m_level++;
403         std::size_t start = 0;
404         lt = replace_macros(lt);
405         pstring_list_t t = pstring_list_t::splitexpr(lt.substr(3).replace(" ",""), m_expr_sep);
406         int val = expr(t, start, 0);
407         if (val == 0)
408            m_ifflag |= (1 << m_level);
409      }
410      else if (lti[0].equals("#ifdef"))
411      {
412         m_level++;
413         if (get_define(lti[1]) == NULL)
414            m_ifflag |= (1 << m_level);
415      }
416      else if (lti[0].equals("#ifndef"))
417      {
418         m_level++;
419         if (get_define(lti[1]) != NULL)
420            m_ifflag |= (1 << m_level);
421      }
422      else if (lti[0].equals("#else"))
423      {
424         m_ifflag ^= (1 << m_level);
425      }
426      else if (lti[0].equals("#endif"))
427      {
428         m_ifflag &= ~(1 << m_level);
429         m_level--;
430      }
431      else if (lti[0].equals("#include"))
432      {
433         // ignore
434      }
435      else if (lti[0].equals("#pragma"))
436      {
437         if (m_ifflag == 0 && lti.size() > 3 && lti[1].equals("NETLIST"))
438         {
439            if (lti[2].equals("warning"))
440               error("NETLIST: " + catremainder(lti, 3, " "));
441         }
442      }
443      else if (lti[0].equals("#define"))
444      {
445         if (m_ifflag == 0)
446         {
447            if (lti.size() != 3)
448               error("PREPRO: only simple defines allowed: " + line);
449            m_defines.add(lti[1], define_t(lti[1], lti[2]));
450         }
451      }
452      else
453         error(pfmt("unknown directive on line {1}: {2}")(m_lineno)(line));
454   }
455   else
456   {
457      lt = replace_macros(lt);
458      if (m_ifflag == 0)
459      {
460         ret.cat(lt);
461         ret.cat("\n");
462      }
463   }
464   return ret;
465}
466
467
468postream & ppreprocessor::process_i(pistream &istrm, postream &ostrm)
469{
470   pstring line;
471   while (istrm.readline(line))
472   {
473      line = process_line(line);
474      ostrm.writeline(line);
475   }
476   return ostrm;
477}
478
479
480#if (defined(__MINGW32__) && (__GNUC__ >= 5))
481#pragma GCC diagnostic pop
482#endif
trunk/src/lib/netlist/plib/pparser.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * pparser.h
5 *
6 */
7
8#ifndef PPARSER_H_
9#define PPARSER_H_
10
11#include "pconfig.h"
12#include "pstring.h"
13#include "plists.h"
14#include "pstream.h"
15
16class ptokenizer
17{
18   P_PREVENT_COPYING(ptokenizer)
19public:
20   virtual ~ptokenizer() {}
21
22   ptokenizer(pistream &strm)
23   : m_strm(strm), m_lineno(1), m_px(0), m_string('"')
24   {}
25
26   enum token_type
27   {
28      IDENTIFIER,
29      NUMBER,
30      TOKEN,
31      STRING,
32      COMMENT,
33      UNKNOWN,
34      ENDOFFILE
35   };
36
37   struct token_id_t
38   {
39   public:
40      token_id_t() : m_id(-2) {}
41      token_id_t(const int id) : m_id(id) {}
42      int id() const { return m_id; }
43   private:
44      int m_id;
45   };
46
47   struct token_t
48   {
49      token_t(token_type type)
50      {
51         m_type = type;
52         m_id = token_id_t(-1);
53         m_token ="";
54      }
55      token_t(token_type type, const pstring &str)
56      {
57         m_type = type;
58         m_id = token_id_t(-1);
59         m_token = str;
60      }
61      token_t(const token_id_t id, const pstring &str)
62      {
63         m_type = TOKEN;
64         m_id = id;
65         m_token = str;
66      }
67
68      bool is(const token_id_t &tok_id) const { return m_id.id() == tok_id.id(); }
69      bool is_not(const token_id_t &tok_id) const { return !is(tok_id); }
70
71      bool is_type(const token_type type) const { return m_type == type; }
72
73      pstring str() const { return m_token; }
74
75   private:
76      token_type m_type;
77      token_id_t m_id;
78      pstring m_token;
79   };
80
81
82   int currentline_no() { return m_lineno; }
83   pstring currentline_str();
84
85   /* tokenizer stuff follows ... */
86
87   token_t get_token();
88   pstring get_string();
89   pstring get_identifier();
90   pstring get_identifier_or_number();
91   double get_number_double();
92   long get_number_long();
93
94   void require_token(const token_id_t &token_num);
95   void require_token(const token_t tok, const token_id_t &token_num);
96
97   token_id_t register_token(pstring token)
98   {
99      m_tokens.add(token);
100      return token_id_t(m_tokens.size() - 1);
101   }
102
103   void set_identifier_chars(pstring s) { m_identifier_chars = s; }
104   void set_number_chars(pstring st, pstring rem) { m_number_chars_start = st; m_number_chars = rem; }
105   void set_string_char(char c) { m_string = c; }
106   void set_whitespace(pstring s) { m_whitespace = s; }
107   void set_comment(pstring start, pstring end, pstring line)
108   {
109      m_tok_comment_start = register_token(start);
110      m_tok_comment_end = register_token(end);
111      m_tok_line_comment = register_token(line);
112   }
113
114   token_t get_token_internal();
115   void error(const pstring &errs);
116
117protected:
118   virtual void verror(const pstring &msg, int line_num, const pstring &line) = 0;
119
120private:
121   void skipeol();
122
123   pstring::code_t getc();
124   void ungetc();
125
126   bool eof() { return m_strm.eof(); }
127
128   pistream &m_strm;
129
130   int m_lineno;
131   pstring m_cur_line;
132   unsigned m_px;
133
134   /* tokenizer stuff follows ... */
135
136   pstring m_identifier_chars;
137   pstring m_number_chars;
138   pstring m_number_chars_start;
139   plist_t<pstring> m_tokens;
140   pstring m_whitespace;
141   pstring::code_t  m_string;
142
143   token_id_t m_tok_comment_start;
144   token_id_t m_tok_comment_end;
145   token_id_t m_tok_line_comment;
146};
147
148
149class ppreprocessor
150{
151   P_PREVENT_COPYING(ppreprocessor)
152public:
153
154   struct define_t
155   {
156      define_t() { };
157      define_t(const pstring &name, const pstring &replace)
158      : m_name(name), m_replace(replace)
159      {}
160      pstring m_name;
161      pstring m_replace;
162   };
163
164   ppreprocessor();
165   virtual ~ppreprocessor() {}
166
167   template<class ISTR, class OSTR>
168   OSTR &process(ISTR &istrm, OSTR &ostrm)
169   {
170      return dynamic_cast<OSTR &>(process_i(istrm, ostrm));
171   }
172
173protected:
174
175   postream &process_i(pistream &istrm, postream &ostrm);
176
177   double expr(const pstring_list_t &sexpr, std::size_t &start, int prio);
178
179   define_t *get_define(const pstring &name);
180
181   pstring replace_macros(const pstring &line);
182
183   virtual void error(const pstring &err);
184
185private:
186
187   pstring process_line(const pstring &line);
188
189   phashmap_t<pstring, define_t> m_defines;
190   pstring_list_t m_expr_sep;
191
192   //pstringbuffer m_ret;
193   UINT32 m_ifflag; // 31 if levels
194   int m_level;
195   int m_lineno;
196};
197
198#endif /* PPARSER_H_ */
trunk/src/lib/netlist/plib/pstate.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * pstate.c
5 *
6 */
7
8#include "pstate.h"
9
10pstate_manager_t::pstate_manager_t()
11{
12}
13
14pstate_manager_t::~pstate_manager_t()
15{
16   m_save.clear_and_free();
17}
18
19
20
21ATTR_COLD void pstate_manager_t::save_state_ptr(const pstring &stname, const pstate_data_type_e dt, const void *owner, const int size, const int count, void *ptr, bool is_ptr)
22{
23   pstring fullname = stname;
24   ATTR_UNUSED  pstring ts[] = {
25         "NOT_SUPPORTED",
26         "DT_CUSTOM",
27         "DT_DOUBLE",
28#if (PHAS_INT128)
29         "DT_INT128",
30#endif
31         "DT_INT64",
32         "DT_INT16",
33         "DT_INT8",
34         "DT_INT",
35         "DT_BOOLEAN",
36         "DT_FLOAT"
37   };
38
39   pstate_entry_t *p = palloc(pstate_entry_t(stname, dt, owner, size, count, ptr, is_ptr));
40   m_save.add(p);
41}
42
43ATTR_COLD void pstate_manager_t::remove_save_items(const void *owner)
44{
45   pstate_entry_t::list_t todelete;
46
47   for (std::size_t i=0; i < m_save.size(); i++)
48   {
49      if (m_save[i]->m_owner == owner)
50         todelete.add(m_save[i]);
51   }
52   for (std::size_t i=0; i < todelete.size(); i++)
53   {
54      m_save.remove(todelete[i]);
55   }
56   todelete.clear_and_free();
57}
58
59ATTR_COLD void pstate_manager_t::pre_save()
60{
61   for (std::size_t i=0; i < m_save.size(); i++)
62      if (m_save[i]->m_dt == DT_CUSTOM)
63         m_save[i]->m_callback->on_pre_save();
64}
65
66ATTR_COLD void pstate_manager_t::post_load()
67{
68   for (std::size_t i=0; i < m_save.size(); i++)
69      if (m_save[i]->m_dt == DT_CUSTOM)
70         m_save[i]->m_callback->on_post_load();
71}
72
73template<> ATTR_COLD void pstate_manager_t::save_item(pstate_callback_t &state, const void *owner, const pstring &stname)
74{
75   //save_state_ptr(stname, DT_CUSTOM, 0, 1, &state);
76   pstate_callback_t *state_p = &state;
77   pstate_entry_t *p = palloc(pstate_entry_t(stname, owner, state_p));
78   m_save.add(p);
79   state.register_state(*this, stname);
80}
trunk/src/lib/netlist/plib/pstate.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * pstate.h
5 *
6 */
7
8#ifndef PSTATE_H_
9#define PSTATE_H_
10
11#include "plists.h"
12#include "pstring.h"
13
14// ----------------------------------------------------------------------------------------
15// state saving ...
16// ----------------------------------------------------------------------------------------
17
18#define PSTATE_INTERFACE_DECL()               \
19   template<typename C> ATTR_COLD void save(C &state, const pstring &stname); \
20   template<typename C, std::size_t N> ATTR_COLD void save(C (&state)[N], const pstring &stname); \
21   template<typename C> ATTR_COLD void save(C *state, const pstring &stname, const int count);
22
23#define PSTATE_INTERFACE(obj, manager, module)               \
24   template<typename C> ATTR_COLD void obj::save(C &state, const pstring &stname) \
25   { manager->save_item(state, this, module + "." + stname); } \
26   template<typename C, std::size_t N> ATTR_COLD void obj::save(C (&state)[N], const pstring &stname) \
27   { manager->save_state_ptr(module + "." + stname, pstate_datatype<C>::type, this, sizeof(state[0]), N, &(state[0]), false); } \
28   template<typename C> ATTR_COLD void obj::save(C *state, const pstring &stname, const int count) \
29   { manager->save_state_ptr(module + "." + stname, pstate_datatype<C>::type, this, sizeof(C), count, state, false);   }
30
31enum pstate_data_type_e {
32   NOT_SUPPORTED,
33   DT_CUSTOM,
34   DT_DOUBLE,
35#if (PHAS_INT128)
36   DT_INT128,
37#endif
38   DT_INT64,
39   DT_INT16,
40   DT_INT8,
41   DT_INT,
42   DT_BOOLEAN,
43   DT_FLOAT
44};
45
46template<typename _ItemType> struct pstate_datatype
47{
48   static const pstate_data_type_e type = pstate_data_type_e(NOT_SUPPORTED);
49   static const bool is_ptr = false;
50};
51
52template<typename _ItemType> struct pstate_datatype<_ItemType *>
53{
54   static const pstate_data_type_e type = pstate_data_type_e(NOT_SUPPORTED);
55   static const bool is_ptr = true;
56};
57
58//template<typename _ItemType> struct type_checker<_ItemType*> { static const bool is_atom = false; static const bool is_pointer = true; };
59
60#define NETLIST_SAVE_TYPE(TYPE, TYPEDESC) \
61      template<> struct pstate_datatype<TYPE>{ static const pstate_data_type_e type = pstate_data_type_e(TYPEDESC); static const bool is_ptr = false;}; \
62      template<> struct pstate_datatype<TYPE *>{ static const pstate_data_type_e type = pstate_data_type_e(TYPEDESC); static const bool is_ptr = true;}
63
64NETLIST_SAVE_TYPE(char, DT_INT8);
65NETLIST_SAVE_TYPE(double, DT_DOUBLE);
66NETLIST_SAVE_TYPE(float, DT_FLOAT);
67NETLIST_SAVE_TYPE(INT8, DT_INT8);
68NETLIST_SAVE_TYPE(UINT8, DT_INT8);
69#if (PHAS_INT128)
70NETLIST_SAVE_TYPE(INT128, DT_INT128);
71NETLIST_SAVE_TYPE(UINT128, DT_INT128);
72#endif
73NETLIST_SAVE_TYPE(INT64, DT_INT64);
74NETLIST_SAVE_TYPE(UINT64, DT_INT64);
75NETLIST_SAVE_TYPE(bool, DT_BOOLEAN);
76NETLIST_SAVE_TYPE(UINT32, DT_INT);
77NETLIST_SAVE_TYPE(INT32, DT_INT);
78NETLIST_SAVE_TYPE(UINT16, DT_INT16);
79NETLIST_SAVE_TYPE(INT16, DT_INT16);
80//NETLIST_SAVE_TYPE(std::size_t, DT_INT64);
81
82class pstate_manager_t;
83
84class pstate_callback_t
85{
86public:
87   typedef plist_t<pstate_callback_t *> list_t;
88
89   virtual ~pstate_callback_t() { };
90
91   virtual void register_state(pstate_manager_t &manager, const pstring &module) = 0;
92   virtual void on_pre_save() = 0;
93   virtual void on_post_load() = 0;
94protected:
95};
96
97struct pstate_entry_t
98{
99   typedef plist_t<pstate_entry_t *> list_t;
100
101   pstate_entry_t(const pstring &stname, const pstate_data_type_e dt, const void *owner,
102         const int size, const int count, void *ptr, bool is_ptr)
103   : m_name(stname), m_dt(dt), m_owner(owner), m_callback(NULL), m_size(size), m_count(count), m_ptr(ptr), m_is_ptr(is_ptr) { }
104
105   pstate_entry_t(const pstring &stname, const void *owner, pstate_callback_t *callback)
106   : m_name(stname), m_dt(DT_CUSTOM), m_owner(owner), m_callback(callback), m_size(0), m_count(0), m_ptr(NULL), m_is_ptr(false) { }
107
108   ~pstate_entry_t() { }
109
110   pstring m_name;
111   const pstate_data_type_e m_dt;
112   const void *m_owner;
113   pstate_callback_t *m_callback;
114   const int m_size;
115   const int m_count;
116   void *m_ptr;
117   bool m_is_ptr;
118
119   template<typename T>
120   T *resolved()
121   {
122      if (m_is_ptr)
123         return *static_cast<T **>(m_ptr);
124      else
125         return static_cast<T *>(m_ptr);
126   }
127};
128
129class pstate_manager_t
130{
131public:
132
133   pstate_manager_t();
134   ~pstate_manager_t();
135
136   template<typename C> ATTR_COLD void save_item(C &state, const void *owner, const pstring &stname)
137   {
138      save_state_ptr(stname, pstate_datatype<C>::type, owner, sizeof(C), 1, &state, pstate_datatype<C>::is_ptr);
139   }
140
141   template<typename C, std::size_t N> ATTR_COLD void save_item(C (&state)[N], const void *owner, const pstring &stname)
142   {
143      save_state_ptr(stname, pstate_datatype<C>::type, owner, sizeof(state[0]), N, &(state[0]), false);
144   }
145
146   template<typename C> ATTR_COLD void save_item(C *state, const void *owner, const pstring &stname, const int count)
147   {
148      save_state_ptr(stname, pstate_datatype<C>::type, owner, sizeof(C), count, state, false);
149   }
150
151   ATTR_COLD void pre_save();
152   ATTR_COLD void post_load();
153   ATTR_COLD void remove_save_items(const void *owner);
154
155   const pstate_entry_t::list_t &save_list() const { return m_save; }
156
157   ATTR_COLD void save_state_ptr(const pstring &stname, const pstate_data_type_e, const void *owner, const int size, const int count, void *ptr, bool is_ptr);
158
159protected:
160
161private:
162   pstate_entry_t::list_t m_save;
163};
164
165template<> ATTR_COLD void pstate_manager_t::save_item(pstate_callback_t &state, const void *owner, const pstring &stname);
166
167
168#endif /* PSTATE_H_ */
trunk/src/lib/netlist/plib/pstream.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * pstream.c
5 *
6 */
7
8#include <cstdio>
9#include <cstring>
10#include <cstdlib>
11#include <algorithm>
12
13#include "pstream.h"
14#include "palloc.h"
15
16// -----------------------------------------------------------------------------
17// Input file stream
18// -----------------------------------------------------------------------------
19
20pifilestream::pifilestream(const pstring &fname) : pistream(0), m_pos(0)
21{
22   m_file = fopen(fname.cstr(), "rb");
23   if (m_file == NULL)
24   {
25      set_flag(FLAG_ERROR);
26      set_flag(FLAG_EOF);
27      set_flag(FLAG_CLOSED);
28   }
29   else
30   {
31      if (ftell((FILE *) m_file) >= 0)
32      {
33         if (fseek((FILE *) m_file, 0, SEEK_SET) >= 0)
34            set_flag(FLAG_SEEKABLE);
35      }
36   }
37}
38
39pifilestream::~pifilestream()
40{
41   if (!closed())
42      close();
43}
44
45void pifilestream::close()
46{
47   fclose((FILE *) m_file);
48   set_flag(FLAG_CLOSED);
49}
50
51unsigned pifilestream::vread(void *buf, unsigned n)
52{
53   std::size_t r = fread(buf, 1, n, (FILE *) m_file);
54   if (r < n)
55   {
56      if (feof((FILE *) m_file))
57         set_flag(FLAG_EOF);
58      if (ferror((FILE *) m_file))
59         set_flag(FLAG_ERROR);
60   }
61   m_pos += r;
62   return r;
63}
64
65void pifilestream::vseek(pos_type n)
66{
67   check_seekable();
68   if (fseek((FILE *) m_file, SEEK_SET, n) < 0)
69      set_flag(FLAG_ERROR);
70   else
71      m_pos = n;
72   if (feof((FILE *) m_file))
73      set_flag(FLAG_EOF);
74   else
75      clear_flag(FLAG_EOF);
76   if (ferror((FILE *) m_file))
77      set_flag(FLAG_ERROR);
78}
79
80pifilestream::pos_type pifilestream::vtell()
81{
82   long ret = ftell((FILE *) m_file);
83   if (ret < 0)
84   {
85      return m_pos;
86   }
87   else
88      return ret;
89}
90
91// -----------------------------------------------------------------------------
92// Output file stream
93// -----------------------------------------------------------------------------
94
95pofilestream::pofilestream(const pstring &fname) : postream(0), m_pos(0)
96{
97   m_file = fopen(fname.cstr(), "wb");
98   if (m_file == NULL)
99   {
100      set_flag(FLAG_ERROR);
101      set_flag(FLAG_CLOSED);
102   }
103   else
104   {
105      if (ftell((FILE *) m_file) >= 0)
106      {
107         if (fseek((FILE *) m_file, 0, SEEK_SET) >= 0)
108            set_flag(FLAG_SEEKABLE);
109      }
110   }
111}
112
113pofilestream::~pofilestream()
114{
115   if (!closed())
116      close();
117}
118
119void pofilestream::close()
120{
121   fclose((FILE *) m_file);
122   set_flag(FLAG_CLOSED);
123}
124
125void pofilestream::vwrite(const void *buf, unsigned n)
126{
127   std::size_t r = fwrite(buf, 1, n, (FILE *) m_file);
128   if (r < n)
129   {
130      if (ferror((FILE *) m_file))
131         set_flag(FLAG_ERROR);
132   }
133   m_pos += r;
134}
135
136void pofilestream::vseek(pos_type n)
137{
138   check_seekable();
139   if (fseek((FILE *) m_file, SEEK_SET, n) < 0)
140      set_flag(FLAG_ERROR);
141   else
142   {
143      m_pos = n;
144      if (ferror((FILE *) m_file))
145         set_flag(FLAG_ERROR);
146   }
147}
148
149pifilestream::pos_type pofilestream::vtell()
150{
151   long ret = ftell((FILE *) m_file);
152   if (ret < 0)
153   {
154      return m_pos;
155   }
156   else
157      return ret;
158}
159
160// -----------------------------------------------------------------------------
161// Memory stream
162// -----------------------------------------------------------------------------
163
164pimemstream::pimemstream(const void *mem, const pos_type len)
165   : pistream(FLAG_SEEKABLE), m_pos(0), m_len(len), m_mem((char *) mem)
166{
167}
168
169pimemstream::pimemstream(const pomemstream &ostrm)
170: pistream(FLAG_SEEKABLE), m_pos(0), m_len(ostrm.size()), m_mem((char *) ostrm.memory())
171{
172}
173
174pimemstream::~pimemstream()
175{
176}
177
178unsigned pimemstream::vread(void *buf, unsigned n)
179{
180   unsigned ret = (m_pos + n <= m_len) ? n :  m_len - m_pos;
181
182   if (ret > 0)
183   {
184      memcpy(buf, m_mem + m_pos, ret);
185      m_pos += ret;
186   }
187
188   if (ret < n)
189      set_flag(FLAG_EOF);
190
191   return ret;
192}
193
194void pimemstream::vseek(pos_type n)
195{
196   m_pos = (n>=m_len) ? m_len : n;
197   clear_flag(FLAG_EOF);
198
199}
200
201pimemstream::pos_type pimemstream::vtell()
202{
203   return m_pos;
204}
205
206// -----------------------------------------------------------------------------
207// Output memory stream
208// -----------------------------------------------------------------------------
209
210pomemstream::pomemstream()
211: postream(FLAG_SEEKABLE), m_pos(0), m_capacity(1024), m_size(0)
212{
213   m_mem = palloc_array(char, m_capacity);
214}
215
216pomemstream::~pomemstream()
217{
218   pfree_array(m_mem);
219}
220
221void pomemstream::vwrite(const void *buf, unsigned n)
222{
223   if (m_pos + n >= m_capacity)
224   {
225      while (m_pos + n >= m_capacity)
226         m_capacity *= 2;
227      char *o = m_mem;
228      m_mem = palloc_array(char, m_capacity);
229      if (m_mem == NULL)
230      {
231         set_flag(FLAG_ERROR);
232         return;
233      }
234      memcpy(m_mem, o, m_pos);
235      pfree_array(o);
236   }
237
238   memcpy(m_mem + m_pos, buf, n);
239   m_pos += n;
240   m_size = std::max(m_pos, m_size);
241}
242
243void pomemstream::vseek(pos_type n)
244{
245   m_pos = n;
246   m_size = std::max(m_pos, m_size);
247   if (m_size >= m_capacity)
248   {
249      while (m_size >= m_capacity)
250         m_capacity *= 2;
251      char *o = m_mem;
252      m_mem = palloc_array(char, m_capacity);
253      if (m_mem == NULL)
254      {
255         set_flag(FLAG_ERROR);
256         return;
257      }
258      memcpy(m_mem, o, m_pos);
259      pfree_array(o);
260   }
261}
262
263pstream::pos_type pomemstream::vtell()
264{
265   return m_pos;
266}
trunk/src/lib/netlist/plib/pstream.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * pstream.h
5 */
6
7#ifndef _PSTREAM_H_
8#define _PSTREAM_H_
9
10#include <cstdarg>
11#include <cstddef>
12#include <stdexcept>
13
14#include "pconfig.h"
15#include "pstring.h"
16#include "palloc.h"
17
18// -----------------------------------------------------------------------------
19// pstream: things common to all streams
20// -----------------------------------------------------------------------------
21
22class pstream
23{
24   P_PREVENT_COPYING(pstream)
25public:
26
27   typedef long unsigned pos_type;
28
29   static const pos_type SEEK_EOF = (pos_type) -1;
30
31   pstream(unsigned flags) : m_flags(flags)
32   {
33   }
34   virtual ~pstream()
35   {
36   }
37
38   bool bad() const { return ((m_flags & FLAG_ERROR) != 0); }
39   bool seekable() const { return ((m_flags & FLAG_SEEKABLE) != 0); }
40
41   void seek(pos_type n)
42   {
43      check_seekable();
44      return vseek(n);
45   }
46
47   pos_type tell()
48   {
49      return vtell();
50   }
51
52protected:
53   virtual void vseek(pos_type n) = 0;
54   virtual pos_type vtell() = 0;
55
56   static const unsigned FLAG_EOF = 0x01;
57   static const unsigned FLAG_ERROR = 0x02;
58   static const unsigned FLAG_SEEKABLE = 0x04;
59   static const unsigned FLAG_CLOSED = 0x08;    /* convenience flag */
60
61   bool closed() { return ((m_flags & FLAG_CLOSED) != 0); }
62
63   void set_flag(unsigned flag)
64   {
65      m_flags |= flag;
66   }
67   void clear_flag(unsigned flag)
68   {
69      m_flags &= ~flag;
70   }
71
72   void check_not_eof() const
73   {
74      if (m_flags & FLAG_EOF)
75         throw pexception("unexpected eof");
76   }
77
78   void check_seekable() const
79   {
80      if (!(m_flags & FLAG_SEEKABLE))
81         throw pexception("stream is not seekable");
82   }
83
84   unsigned flags() const { return m_flags; }
85private:
86
87   unsigned m_flags;
88};
89
90// -----------------------------------------------------------------------------
91// pistream: input stream
92// -----------------------------------------------------------------------------
93
94class pistream : public pstream
95{
96   P_PREVENT_COPYING(pistream)
97public:
98
99   pistream(unsigned flags) : pstream(flags) {}
100   virtual ~pistream() {}
101
102   bool eof() const { return ((flags() & FLAG_EOF) != 0) || bad(); }
103
104   /* this digests linux & dos/windows text files */
105
106   bool readline(pstring &line)
107   {
108      UINT8 c = 0;
109      pstringbuffer buf;
110      if (!this->read(c))
111      {
112         line = "";
113         return false;
114      }
115      while (true)
116      {
117         if (c == 10)
118            break;
119         else if (c != 13) /* ignore CR */
120            buf += c;
121         if (!this->read(c))
122            break;
123      }
124      line = buf;
125      return true;
126   }
127
128   bool read(UINT8 &c)
129   {
130      return (read(&c, 1) == 1);
131   }
132
133   unsigned read(void *buf, unsigned n)
134   {
135      return vread(buf, n);
136   }
137
138protected:
139   /* read up to n bytes from stream */
140   virtual unsigned vread(void *buf, unsigned n) = 0;
141
142private:
143};
144
145// -----------------------------------------------------------------------------
146// postream: output stream
147// -----------------------------------------------------------------------------
148
149class postream : public pstream
150{
151   P_PREVENT_COPYING(postream)
152public:
153
154   postream(unsigned flags) : pstream(flags) {}
155   virtual ~postream() {}
156
157   /* this digests linux & dos/windows text files */
158
159   void writeline(const pstring &line)
160   {
161      write(line);
162      write(10);
163   }
164
165   void write(const pstring &text)
166   {
167      write(text.cstr(), text.blen());
168   }
169
170   void write(const char c)
171   {
172      write(&c, 1);
173   }
174
175   void write(const void *buf, unsigned n)
176   {
177      vwrite(buf, n);
178   }
179
180protected:
181   /* write n bytes to stream */
182   virtual void vwrite(const void *buf, unsigned n) = 0;
183
184private:
185};
186
187// -----------------------------------------------------------------------------
188// pomemstream: output string stream
189// -----------------------------------------------------------------------------
190
191class pomemstream : public postream
192{
193   P_PREVENT_COPYING(pomemstream)
194public:
195
196   pomemstream();
197   virtual ~pomemstream();
198
199   char *memory() const { return m_mem; }
200   unsigned size() const { return m_size; }
201
202protected:
203   /* write n bytes to stream */
204   virtual void vwrite(const void *buf, unsigned n);
205   virtual void vseek(pos_type n);
206   virtual pos_type vtell();
207
208private:
209   pos_type m_pos;
210   pos_type m_capacity;
211   pos_type m_size;
212   char *m_mem;
213};
214
215class postringstream : public postream
216{
217   P_PREVENT_COPYING(postringstream )
218
219public:
220
221   postringstream() : postream(0) { }
222   virtual ~postringstream() { }
223
224   const pstringbuffer &str() { return m_buf; }
225
226protected:
227   /* write n bytes to stream */
228   virtual void vwrite(const void *buf, unsigned n)
229   {
230      m_buf.cat(buf, n);
231   }
232   virtual void vseek(pos_type n) { }
233   virtual pos_type vtell() { return m_buf.len(); }
234
235private:
236   pstringbuffer m_buf;
237};
238
239// -----------------------------------------------------------------------------
240// pofilestream: file output stream
241// -----------------------------------------------------------------------------
242
243class pofilestream : public postream
244{
245   P_PREVENT_COPYING(pofilestream)
246public:
247
248   pofilestream(const pstring &fname);
249   virtual ~pofilestream();
250
251   void close();
252
253protected:
254   /* write n bytes to stream */
255   virtual void vwrite(const void *buf, unsigned n);
256   virtual void vseek(pos_type n);
257   virtual pos_type vtell();
258
259private:
260   void *m_file;
261   pos_type m_pos;
262};
263
264// -----------------------------------------------------------------------------
265// pifilestream: file input stream
266// -----------------------------------------------------------------------------
267
268class pifilestream : public pistream
269{
270   P_PREVENT_COPYING(pifilestream)
271public:
272
273   pifilestream(const pstring &fname);
274   virtual ~pifilestream();
275
276   void close();
277
278protected:
279   /* read up to n bytes from stream */
280   virtual unsigned vread(void *buf, unsigned n);
281   virtual void vseek(pos_type n);
282   virtual pos_type vtell();
283
284private:
285   void *m_file;
286   pos_type m_pos;
287};
288
289// -----------------------------------------------------------------------------
290// pimemstream: input memory stream
291// -----------------------------------------------------------------------------
292
293class pimemstream : public pistream
294{
295   P_PREVENT_COPYING(pimemstream)
296public:
297
298   pimemstream(const void *mem, const pos_type len);
299   pimemstream(const pomemstream &ostrm);
300   virtual ~pimemstream();
301
302protected:
303   /* read up to n bytes from stream */
304   virtual unsigned vread(void *buf, unsigned n);
305   virtual void vseek(pos_type n);
306   virtual pos_type vtell();
307
308private:
309   pos_type m_pos;
310   pos_type m_len;
311   char *m_mem;
312};
313
314// -----------------------------------------------------------------------------
315// pistringstream: input string stream
316// -----------------------------------------------------------------------------
317
318class pistringstream : public pimemstream
319{
320   P_PREVENT_COPYING(pistringstream)
321public:
322
323   pistringstream(const pstring &str) : pimemstream(str.cstr(), str.len()), m_str(str) { }
324
325private:
326   /* only needed for a reference till destruction */
327   pstring m_str;
328};
329
330// -----------------------------------------------------------------------------
331// pstream_fmt_writer_t: writer on top of ostream
332// -----------------------------------------------------------------------------
333
334class pstream_fmt_writer_t : public pfmt_writer_t<>
335{
336   P_PREVENT_COPYING(pstream_fmt_writer_t)
337public:
338
339   pstream_fmt_writer_t(postream &strm) : m_strm(strm) {}
340   virtual ~pstream_fmt_writer_t() { }
341
342protected:
343   virtual void vdowrite(const pstring &ls) const
344   {
345      m_strm.write(ls);
346   }
347
348private:
349   postream &m_strm;
350};
351
352#endif /* _PSTREAM_H_ */
trunk/src/lib/netlist/plib/pstring.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nl_string.c
5 *
6 */
7
8#include <cstring>
9//FIXME:: pstring should be locale free
10#include <cctype>
11#include <cstdlib>
12#include <cstdio>
13#include <algorithm>
14
15#include "pstring.h"
16#include "palloc.h"
17#include "plists.h"
18
19template<>
20pstr_t pstring_t<putf8_traits>::m_zero = pstr_t(0);
21template<>
22pstr_t pstring_t<pu8_traits>::m_zero = pstr_t(0);
23
24
25/*
26 * Uncomment the following to override defaults
27 */
28
29#define IMMEDIATE_MODE  (1)
30//#define DEBUG_MODE      (0)
31
32#ifdef MAME_DEBUG
33   #ifndef IMMEDIATE_MODE
34      #define IMMEDIATE_MODE  (1)
35   #endif
36   #ifndef DEBUG_MODE
37      #define DEBUG_MODE      (0)
38   #endif
39#else
40   #ifndef IMMEDIATE_MODE
41      #define IMMEDIATE_MODE  (1)
42   #endif
43   #ifndef DEBUG_MODE
44      #define DEBUG_MODE      (0)
45   #endif
46#endif
47
48template<typename F>
49pstring_t<F>::~pstring_t()
50{
51   sfree(m_ptr);
52}
53
54template<typename F>
55void pstring_t<F>::pcat(const mem_t *s)
56{
57   int slen = strlen(s);
58   pstr_t *n = salloc(m_ptr->len() + slen);
59   if (m_ptr->len() > 0)
60      std::memcpy(n->str(), m_ptr->str(), m_ptr->len());
61   if (slen > 0)
62      std::memcpy(n->str() + m_ptr->len(), s, slen);
63   *(n->str() + n->len()) = 0;
64   sfree(m_ptr);
65   m_ptr = n;
66}
67
68template<typename F>
69void pstring_t<F>::pcat(const pstring_t &s)
70{
71   int slen = s.blen();
72   pstr_t *n = salloc(m_ptr->len() + slen);
73   if (m_ptr->len() > 0)
74      std::memcpy(n->str(), m_ptr->str(), m_ptr->len());
75   if (slen > 0)
76      std::memcpy(n->str() + m_ptr->len(), s.cstr(), slen);
77   *(n->str() + n->len()) = 0;
78   sfree(m_ptr);
79   m_ptr = n;
80}
81
82template<typename F>
83int pstring_t<F>::pcmp(const pstring_t &right) const
84{
85   long l = std::min(blen(), right.blen());
86   if (l == 0)
87   {
88      if (blen() == 0 && right.blen() == 0)
89         return 0;
90      else if (right.blen() == 0)
91         return 1;
92      else
93         return -1;
94   }
95   int ret = memcmp(m_ptr->str(), right.cstr(), l);
96   if (ret == 0)
97      ret = this->blen() - right.blen();
98   if (ret < 0)
99      return -1;
100   else if (ret > 0)
101      return 1;
102   else
103      return 0;
104}
105
106
107template<typename F>
108void pstring_t<F>::pcopy(const mem_t *from, int size)
109{
110   pstr_t *n = salloc(size);
111   if (size > 0)
112      std::memcpy(n->str(), from, size);
113   *(n->str() + size) = 0;
114   sfree(m_ptr);
115   m_ptr = n;
116}
117
118template<typename F>
119const pstring_t<F> pstring_t<F>::substr(int start, int count) const
120{
121   pstring_t ret;
122   int alen = (int) len();
123   if (start < 0)
124      start = 0;
125   if (start >= alen)
126      return ret;
127   if (count <0 || start + count > alen)
128      count = alen - start;
129   const char *p = cstr();
130   if (count <= 0)
131      ret.pcopy(p, 0);
132   else
133   {
134      //FIXME: Trait to tell which one
135      //ret.pcopy(cstr() + start, count);
136      // find start
137      for (int i=0; i<start; i++)
138         p += F::codelen(p);
139      const char *e = p;
140      for (int i=0; i<count; i++)
141         e += F::codelen(e);
142      ret.pcopy(p, e-p);
143   }
144   return ret;
145}
146
147template<typename F>
148const pstring_t<F> pstring_t<F>::ucase() const
149{
150   pstring_t ret = *this;
151   ret.pcopy(cstr(), blen());
152   for (unsigned i=0; i<ret.len(); i++)
153      ret.m_ptr->str()[i] = toupper((unsigned) ret.m_ptr->str()[i]);
154   return ret;
155}
156
157template<typename F>
158int pstring_t<F>::find_first_not_of(const pstring_t &no) const
159{
160   char *t = m_ptr->str();
161   unsigned nolen = no.len();
162   unsigned tlen = len();
163   for (unsigned i=0; i < tlen; i++)
164   {
165      char *n = no.m_ptr->str();
166      bool f = true;
167      for (unsigned j=0; j < nolen; j++)
168      {
169         if (F::code(t) == F::code(n))
170            f = false;
171         n += F::codelen(t);
172      }
173      if (f)
174         return i;
175      t += F::codelen(t);
176   }
177   return -1;
178}
179
180template<typename F>
181int pstring_t<F>::find_last_not_of(const pstring_t &no) const
182{
183   char *t = m_ptr->str();
184   unsigned nolen = no.len();
185   unsigned tlen = len();
186   int last_found = -1;
187   for (unsigned i=0; i < tlen; i++)
188   {
189      char *n = no.m_ptr->str();
190      bool f = true;
191      for (unsigned j=0; j < nolen; j++)
192      {
193         if (F::code(t) == F::code(n))
194            f = false;
195         n += F::codelen(t);
196      }
197      if (f)
198         last_found = i;
199      t += F::codelen(t);
200   }
201   return last_found;
202}
203
204template<typename F>
205pstring_t<F> pstring_t<F>::replace(const pstring_t &search, const pstring_t &replace) const
206{
207   // FIXME: use this pstringbuffer ret = "";
208   pstring_t ret = "";
209   const int slen = search.blen();
210   const int tlen = blen();
211
212   if (slen == 0 || tlen < slen )
213      return *this;
214   int i = 0;
215   while (i < tlen - slen + 1)
216   {
217      if (memcmp(cstr()+i,search.cstr(),slen) == 0)
218      {
219         ret += replace;
220         i += slen;
221      }
222      else
223      {
224         /* avoid adding a code, cat a string ... */
225         mem_t buf[2] = { *(cstr() + i), 0 };
226         ret = ret.cat(buf);
227         i++;
228      }
229   }
230   ret = ret.cat(cstr() + i);
231   return ret;
232}
233
234template<typename F>
235const pstring_t<F> pstring_t<F>::ltrim(const pstring_t &ws) const
236{
237   int f = find_first_not_of(ws);
238   if (f>=0)
239      return substr(f);
240   else
241      return "";
242}
243
244template<typename F>
245const pstring_t<F> pstring_t<F>::rtrim(const pstring_t &ws) const
246{
247   int f = find_last_not_of(ws);
248   if (f>=0)
249      return left(f+1);
250   else
251      return "";
252}
253
254template<typename F>
255const pstring_t<F> pstring_t<F>::rpad(const pstring_t &ws, const unsigned cnt) const
256{
257   // FIXME: pstringbuffer ret(*this);
258
259   pstring_t ret(*this);
260   while (ret.len() < cnt)
261      ret += ws;
262   return pstring_t(ret).substr(0, cnt);
263}
264
265
266template<typename F>
267void pstring_t<F>::pcopy(const mem_t *from)
268{
269   pcopy(from, strlen(from));
270}
271
272template<typename F>
273double pstring_t<F>::as_double(bool *error) const
274{
275   double ret;
276   char *e = NULL;
277
278   if (error != NULL)
279      *error = false;
280   ret = strtod(cstr(), &e);
281   if (*e != 0)
282      if (error != NULL)
283         *error = true;
284   return ret;
285}
286
287template<typename F>
288long pstring_t<F>::as_long(bool *error) const
289{
290   long ret;
291   char *e = NULL;
292
293   if (error != NULL)
294      *error = false;
295   if (startsWith("0x"))
296      ret = strtol(substr(2).cstr(), &e, 16);
297   else
298      ret = strtol(cstr(), &e, 10);
299   if (*e != 0)
300      if (error != NULL)
301         *error = true;
302   return ret;
303}
304
305// ----------------------------------------------------------------------------------------
306// static stuff ...
307// ----------------------------------------------------------------------------------------
308
309/*
310 * Cached allocation of string memory
311 *
312 * This improves startup performance by 30%.
313 */
314
315#if 1
316
317static pstack_t<pstr_t *> *stk = NULL;
318
319static inline unsigned countleadbits(unsigned x)
320{
321#ifndef count_leading_zeros
322   unsigned msk;
323   unsigned ret;
324   if (x < 0x100)
325   {
326      msk = 0x80;
327      ret = 24;
328   }
329   else if (x < 0x10000)
330   {
331      msk = 0x8000;
332      ret = 16;
333   }
334   else if (x < 0x1000000)
335   {
336      msk = 0x800000;
337      ret = 8;
338   }
339   else
340   {
341      msk = 0x80000000;
342      ret = 0;
343   }
344   while ((msk & x) == 0 && ret < 31)
345   {
346      msk = msk >> 1;
347      ret++;
348   }
349   return ret;
350#else
351   return count_leading_zeros(x);
352#endif
353}
354
355template<typename F>
356void pstring_t<F>::sfree(pstr_t *s)
357{
358   s->m_ref_count--;
359   if (s->m_ref_count == 0 && s != &m_zero)
360   {
361      if (stk != NULL)
362      {
363         unsigned sn= ((32 - countleadbits(s->len())) + 1) / 2;
364         stk[sn].push(s);
365      }
366      else
367         pfree_array(((char *)s));
368      //_mm_free(((char *)s));
369   }
370}
371
372template<typename F>
373pstr_t *pstring_t<F>::salloc(int n)
374{
375   if (stk == NULL)
376      stk = palloc_array(pstack_t<pstr_t *>, 17);
377   pstr_t *p;
378   unsigned sn= ((32 - countleadbits(n)) + 1) / 2;
379   unsigned size = sizeof(pstr_t) + (1<<(sn * 2)) + 1;
380   if (stk[sn].empty())
381      p = (pstr_t *) palloc_array(char, size);
382   else
383   {
384      //printf("%u %u\n", sn, (unsigned) stk[sn].count());
385      p = stk[sn].pop();
386   }
387
388   //  str_t *p = (str_t *) _mm_malloc(size, 8);
389   p->init(n);
390   return p;
391}
392template<typename F>
393void pstring_t<F>::resetmem()
394{
395   if (stk != NULL)
396   {
397      for (unsigned i=0; i<=16; i++)
398      {
399         for (; stk[i].count() > 0; )
400            pfree_array(stk[i].pop());
401      }
402      pfree_array(stk);
403      stk = NULL;
404   }
405}
406
407
408#else
409template<typename F>
410void pstring_t<F>::sfree(pstr_t *s)
411{
412   s->m_ref_count--;
413   if (s->m_ref_count == 0 && s != &m_zero)
414   {
415      pfree_array(((char *)s));
416      //_mm_free(((char *)s));
417   }
418}
419
420template<typename F>
421pstr_t *pstring_t<F>::salloc(int n)
422{
423   int size = sizeof(pstr_t) + n + 1;
424   pstr_t *p = (pstr_t *) palloc_array(char, size);
425   //  str_t *p = (str_t *) _mm_malloc(size, 8);
426   p->init(n);
427   return p;
428}
429
430template<typename F>
431void pstring_t<F>::resetmem()
432{
433   // Release the 0 string
434}
435#endif
436
437
438// ----------------------------------------------------------------------------------------
439// pstring ...
440// ----------------------------------------------------------------------------------------
441
442const pstring::type_t pstring::vprintf(va_list args) const
443{
444   // sprintf into the temporary buffer
445   char tempbuf[4096];
446   std::vsprintf(tempbuf, cstr(), args);
447
448   return type_t(tempbuf);
449}
450
451
452const pstring::type_t pstring::sprintf(const char *format, ...)
453{
454   va_list ap;
455   va_start(ap, format);
456   type_t ret = pstring(format).vprintf(ap);
457   va_end(ap);
458   return ret;
459}
460
461template<typename F>
462int pstring_t<F>::find(const pstring_t &search, unsigned start) const
463{
464   const unsigned tlen = len();
465   const unsigned slen = search.len();
466   const char *s = search.cstr();
467   const unsigned startt = std::min(start, tlen);
468   const char *t = cstr();
469   for (unsigned i=0; i<startt; i++)
470      t += F::codelen(t);
471   for (int i=0; i <= (int) tlen - (int) startt - (int) slen; i++)
472   {
473      if (F::code(t) == F::code(s))
474         if (std::memcmp(t,s,search.blen())==0)
475            return i+startt;
476      t += F::codelen(t);
477   }
478   return -1;
479}
480
481template<typename F>
482int pstring_t<F>::find(const mem_t *search, unsigned start) const
483{
484   const unsigned tlen = len();
485   unsigned slen = 0;
486   unsigned sblen = 0;
487   const mem_t *x = search;
488   while (*x != 0)
489   {
490      slen++;
491      const unsigned sl = F::codelen(x);
492      x += sl;
493      sblen += sl;
494   }
495   const char *s = search;
496   const unsigned startt = std::min(start, tlen);
497   const char *t = cstr();
498   for (unsigned i=0; i<startt; i++)
499      t += F::codelen(t);
500   for (int i=0; i <= (int) tlen - (int) startt - (int) slen; i++)
501   {
502      if (F::code(t) == F::code(s))
503         if (std::memcmp(t,s,sblen)==0)
504            return i+startt;
505      t += F::codelen(t);
506   }
507   return -1;
508}
509
510template<typename F>
511bool pstring_t<F>::startsWith(const pstring_t &arg) const
512{
513   if (arg.blen() > blen())
514      return false;
515   else
516      return (memcmp(arg.cstr(), cstr(), arg.len()) == 0);
517}
518
519template<typename F>
520bool pstring_t<F>::endsWith(const pstring_t &arg) const
521{
522   if (arg.blen() > blen())
523      return false;
524   else
525      return (memcmp(cstr()+this->len()-arg.len(), arg.cstr(), arg.len()) == 0);
526}
527
528
529template<typename F>
530bool pstring_t<F>::startsWith(const mem_t *arg) const
531{
532   unsigned alen = strlen(arg);
533   if (alen > blen())
534      return false;
535   else
536      return (memcmp(arg, cstr(), alen) == 0);
537}
538
539template<typename F>
540int pstring_t<F>::pcmp(const mem_t *right) const
541{
542   return std::strcmp(m_ptr->str(), right);
543}
544
545// ----------------------------------------------------------------------------------------
546// pstringbuffer
547// ----------------------------------------------------------------------------------------
548
549pstringbuffer::~pstringbuffer()
550{
551   if (m_ptr != NULL)
552      pfree_array(m_ptr);
553}
554
555void pstringbuffer::resize(const std::size_t size)
556{
557   if (m_ptr == NULL)
558   {
559      m_size = DEFAULT_SIZE;
560      while (m_size <= size)
561         m_size *= 2;
562      m_ptr = palloc_array(char, m_size);
563      *m_ptr = 0;
564      m_len = 0;
565   }
566   else if (m_size < size)
567   {
568      while (m_size < size)
569         m_size *= 2;
570      char *new_buf = palloc_array(char, m_size);
571      std::memcpy(new_buf, m_ptr, m_len + 1);
572      pfree_array(m_ptr);
573      m_ptr = new_buf;
574   }
575}
576
577void pstringbuffer::pcopy(const char *from)
578{
579   std::size_t nl = strlen(from) + 1;
580   resize(nl);
581   std::memcpy(m_ptr, from, nl);
582}
583
584void pstringbuffer::pcopy(const pstring &from)
585{
586   std::size_t nl = from.blen() + 1;
587   resize(nl);
588   std::memcpy(m_ptr, from.cstr(), nl);
589}
590
591void pstringbuffer::pcat(const char *s)
592{
593   const std::size_t slen = std::strlen(s);
594   const std::size_t nl = m_len + slen + 1;
595   resize(nl);
596   std::memcpy(m_ptr + m_len, s, slen + 1);
597   m_len += slen;
598}
599
600void pstringbuffer::pcat(const void *m, unsigned l)
601{
602   const std::size_t nl = m_len + l + 1;
603   resize(nl);
604   std::memcpy(m_ptr + m_len, m, l);
605   m_len += l;
606   *(m_ptr + m_len) = 0;
607}
608
609void pstringbuffer::pcat(const pstring &s)
610{
611   const std::size_t slen = s.blen();
612   const std::size_t nl = m_len + slen + 1;
613   resize(nl);
614   std::memcpy(m_ptr + m_len, s.cstr(), slen);
615   m_len += slen;
616   m_ptr[m_len] = 0;
617}
618
619pfmt::pfmt(const pstring &fmt)
620: m_arg(0)
621{
622   memcpy(m_str, fmt.cstr(), fmt.blen() + 1);
623}
624
625pfmt::pfmt(const char *fmt)
626: m_arg(0)
627{
628   strncpy(m_str, fmt, sizeof(m_str) - 1);
629   m_str[sizeof(m_str) - 1] = 0;
630}
631
632#if 0
633void pformat::format_element(const char *f, const char *l, const char *fmt_spec,  ...)
634{
635   va_list ap;
636   va_start(ap, fmt_spec);
637   char fmt[30] = "%";
638   char search[10] = "";
639   char buf[1024];
640   strcat(fmt, f);
641   strcat(fmt, l);
642   strcat(fmt, fmt_spec);
643   int nl = vsprintf(buf, fmt, ap);
644   m_arg++;
645   int sl = sprintf(search, "%%%d", m_arg);
646   char *p = strstr(m_str, search);
647   if (p != NULL)
648   {
649      // Make room
650      memmove(p+nl, p+sl, strlen(p) + 1 - sl);
651      memcpy(p, buf, nl);
652   }
653   va_end(ap);
654}
655#else
656void pfmt::format_element(const char *f, const char *l, const char *fmt_spec,  ...)
657{
658   va_list ap;
659   va_start(ap, fmt_spec);
660   char fmt[30] = "%";
661   char search[10] = "";
662   char buf[1024];
663   m_arg++;
664   int sl = sprintf(search, "{%d:", m_arg);
665   char *p = strstr(m_str, search);
666   if (p == NULL)
667   {
668      sl = sprintf(search, "{%d}", m_arg);
669      p = strstr(m_str, search);
670      if (p == NULL)
671      {
672         sl = 2;
673         p = strstr(m_str, "{}");
674      }
675      strcat(fmt, f);
676   }
677   else
678   {
679      char *p1 = strstr(p, "}");
680      if (p1 != NULL)
681      {
682         sl = p1 - p + 1;
683         if (m_arg>=10)
684            strncat(fmt, p+4, p1 - p - 4);
685         else
686            strncat(fmt, p+3, p1 - p - 3);
687      }
688      else
689         strcat(fmt, f);
690   }
691   strcat(fmt, l);
692   strcat(fmt, fmt_spec);
693   int nl = vsprintf(buf, fmt, ap);
694   if (p != NULL)
695   {
696      // Make room
697      memmove(p+nl, p+sl, strlen(p) + 1 - sl);
698      memcpy(p, buf, nl);
699   }
700   va_end(ap);
701}
702#endif
703
704template struct pstring_t<pu8_traits>;
705template struct pstring_t<putf8_traits>;
trunk/src/lib/netlist/plib/pstring.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * pstring.h
5 */
6
7#ifndef _PSTRING_H_
8#define _PSTRING_H_
9
10#include <cstdarg>
11#include <cstddef>
12
13#include "pconfig.h"
14
15// ----------------------------------------------------------------------------------------
16// pstring: immutable strings ...
17//
18// pstrings are just a pointer to a "pascal-style" string representation.
19// It uses reference counts and only uses new memory when a string changes.
20// ----------------------------------------------------------------------------------------
21
22   struct pstr_t
23   {
24      //str_t() : m_ref_count(1), m_len(0) { m_str[0] = 0; }
25      pstr_t(const unsigned alen)
26      {
27         init(alen);
28      }
29      void init(const unsigned alen)
30      {
31            m_ref_count = 1;
32            m_len = alen;
33            m_str[0] = 0;
34      }
35      char *str() { return &m_str[0]; }
36      unsigned len() const  { return m_len; }
37      int m_ref_count;
38   private:
39      unsigned m_len;
40      char m_str[1];
41   };
42
43
44template <typename F>
45struct pstring_t
46{
47public:
48   typedef F traits;
49
50   typedef typename traits::mem_t mem_t;
51   typedef typename traits::code_t code_t;
52
53   // simple construction/destruction
54   pstring_t()
55   {
56      init();
57   }
58   ~pstring_t();
59
60   // construction with copy
61   pstring_t(const mem_t *string) {init(); if (string != NULL && *string != 0) pcopy(string); }
62   pstring_t(const pstring_t &string) {init(); pcopy(string); }
63
64   // assignment operators
65   pstring_t &operator=(const mem_t *string) { pcopy(string); return *this; }
66   pstring_t &operator=(const pstring_t &string) { pcopy(string); return *this; }
67
68   // C string conversion helpers
69   const mem_t *cstr() const { return m_ptr->str(); }
70
71   // concatenation operators
72   pstring_t& operator+=(const pstring_t &string) { pcat(string); return *this; }
73   pstring_t& operator+=(const mem_t *string) { pcat(string); return *this; }
74   friend pstring_t operator+(const pstring_t &lhs, const pstring_t &rhs) { return pstring_t(lhs) += rhs; }
75   friend pstring_t operator+(const pstring_t &lhs, const mem_t *rhs) { return pstring_t(lhs) += rhs; }
76   friend pstring_t operator+(const mem_t *lhs, const pstring_t &rhs) { return pstring_t(lhs) += rhs; }
77
78   // comparison operators
79   bool operator==(const mem_t *string) const { return (pcmp(string) == 0); }
80   bool operator==(const pstring_t &string) const { return (pcmp(string) == 0); }
81   bool operator!=(const mem_t *string) const { return (pcmp(string) != 0); }
82   bool operator!=(const pstring_t &string) const { return (pcmp(string) != 0); }
83
84   bool operator<(const mem_t *string) const { return (pcmp(string) < 0); }
85   bool operator<(const pstring_t &string) const { return (pcmp(string) < 0); }
86   bool operator<=(const mem_t *string) const { return (pcmp(string) <= 0); }
87   bool operator<=(const pstring_t &string) const { return (pcmp(string) <= 0); }
88   bool operator>(const mem_t *string) const { return (pcmp(string) > 0); }
89   bool operator>(const pstring_t &string) const { return (pcmp(string) > 0); }
90   bool operator>=(const mem_t *string) const { return (pcmp(string) >= 0); }
91   bool operator>=(const pstring_t &string) const { return (pcmp(string) >= 0); }
92
93   bool equals(const pstring_t &string) const { return (pcmp(string) == 0); }
94
95   int cmp(const pstring_t &string) const { return pcmp(string); }
96   int cmp(const mem_t *string) const { return pcmp(string); }
97
98   bool startsWith(const pstring_t &arg) const;
99   bool startsWith(const mem_t *arg) const;
100
101   bool endsWith(const pstring_t &arg) const;
102   bool endsWith(const mem_t *arg) const { return endsWith(pstring_t(arg)); }
103
104   pstring_t replace(const pstring_t &search, const pstring_t &replace) const;
105
106   const pstring_t cat(const pstring_t &s) const { return *this + s; }
107   const pstring_t cat(const mem_t *s) const { return *this + s; }
108
109   unsigned blen() const { return m_ptr->len(); }
110
111   // conversions
112
113   double as_double(bool *error = NULL) const;
114   long as_long(bool *error = NULL) const;
115
116   /*
117    * everything below MAY not work for utf8.
118    * Example a=s.find(EUROSIGN); b=s.substr(a,1); will deliver invalid utf8
119    */
120
121   unsigned len() const
122   {
123      return F::len(m_ptr);
124   }
125
126   pstring_t& operator+=(const code_t c) { mem_t buf[F::MAXCODELEN+1] = { 0 }; F::encode(c, buf); pcat(buf); return *this; }
127   friend pstring_t operator+(const pstring_t &lhs, const mem_t rhs) { return pstring_t(lhs) += rhs; }
128
129   int find(const pstring_t &search, unsigned start = 0) const;
130   int find(const mem_t *search, unsigned start = 0) const;
131   int find(const code_t search, unsigned start = 0) const { mem_t buf[F::MAXCODELEN+1] = { 0 }; F::encode(search, buf); return find(buf, start); };
132
133   const pstring_t substr(int start, int count = -1) const ;
134
135   const pstring_t left(unsigned count) const { return substr(0, count); }
136   const pstring_t right(unsigned count) const  { return substr((int) len() - (int) count, count); }
137
138   int find_first_not_of(const pstring_t &no) const;
139   int find_last_not_of(const pstring_t &no) const;
140
141   // FIXME:
142   code_t code_at(const unsigned pos) const { return F::code(F::nthcode(m_ptr->str(),pos)); }
143
144   const pstring_t ltrim(const pstring_t &ws = " \t\n\r") const;
145   const pstring_t rtrim(const pstring_t &ws = " \t\n\r") const;
146   const pstring_t trim(const pstring_t &ws = " \t\n\r") const { return this->ltrim(ws).rtrim(ws); }
147
148   const pstring_t rpad(const pstring_t &ws, const unsigned cnt) const;
149
150   const pstring_t ucase() const;
151
152   static void resetmem();
153
154protected:
155
156   pstr_t *m_ptr;
157
158private:
159   void init()
160   {
161      m_ptr = &m_zero;
162      m_ptr->m_ref_count++;
163   }
164
165   int pcmp(const pstring_t &right) const;
166
167   int pcmp(const mem_t *right) const;
168
169   void pcopy(const mem_t *from, int size);
170
171   void pcopy(const mem_t *from);
172
173   void pcopy(const pstring_t &from)
174   {
175      sfree(m_ptr);
176      m_ptr = from.m_ptr;
177      m_ptr->m_ref_count++;
178   }
179
180   void pcat(const mem_t *s);
181   void pcat(const pstring_t &s);
182
183   static pstr_t *salloc(int n);
184   static void sfree(pstr_t *s);
185
186   static pstr_t m_zero;
187};
188
189struct pu8_traits
190{
191   static const unsigned MAXCODELEN = 1; /* in memory units */
192   typedef char mem_t;
193   typedef char code_t;
194   static unsigned len(const pstr_t *p) { return p->len(); }
195   static unsigned codelen(const mem_t *p) { return 1; }
196   static unsigned codelen(const code_t c) { return 1; }
197   static code_t code(const mem_t *p) { return *p; }
198   static void encode(const code_t c, mem_t *p) { *p = c; }
199   static const mem_t *nthcode(const mem_t *p, const unsigned n) { return &(p[n]); }
200};
201
202/* No checking, this may deliver invalid codes */
203struct putf8_traits
204{
205   static const unsigned MAXCODELEN = 4; /* in memory units,  RFC 3629 */
206   typedef char mem_t;
207   typedef unsigned code_t;
208   static unsigned len(pstr_t *p)
209   {
210      unsigned ret = 0;
211      unsigned char *c = (unsigned char *) p->str();
212      while (*c)
213      {
214         if (!((*c & 0xC0) == 0x80))
215            ret++;
216         c++;
217      }
218      return ret;
219   }
220   static unsigned codelen(const mem_t *p)
221   {
222      unsigned char *p1 = (unsigned char *) p;
223      if ((*p1 & 0x80) == 0x00)
224         return 1;
225      else if ((*p1 & 0xE0) == 0xC0)
226         return 2;
227      else if ((*p1 & 0xF0) == 0xE0)
228         return 3;
229      else if ((*p1 & 0xF8) == 0xF0)
230         return 4;
231      else
232      {
233         return 1; // not correct
234      }
235   }
236   static unsigned codelen(const code_t c)
237   {
238      if (c < 0x0080)
239         return 1;
240      else if (c < 0x800)
241         return 2;
242      else if (c < 0x10000)
243         return 3;
244      else /* U+10000 U+1FFFFF */
245         return 4; /* no checks */
246   }
247   static code_t code(const mem_t *p)
248   {
249      unsigned char *p1 = (unsigned char *)p;
250      if ((*p1 & 0x80) == 0x00)
251         return (code_t) *p1;
252      else if ((*p1 & 0xE0) == 0xC0)
253         return ((p1[0] & 0x3f) << 6) | ((p1[1] & 0x3f));
254      else if ((*p1 & 0xF0) == 0xE0)
255         return ((p1[0] & 0x1f) << 12) | ((p1[1] & 0x3f) << 6) | ((p1[2] & 0x3f) << 0);
256      else if ((*p1 & 0xF8) == 0xF0)
257         return ((p1[0] & 0x0f) << 18) | ((p1[1] & 0x3f) << 12) | ((p1[2] & 0x3f) << 6)  | ((p1[3] & 0x3f) << 0);
258      else
259         return *p1; // not correct
260   }
261   static void encode(const code_t c, mem_t *p)
262   {
263      unsigned char *m = (unsigned char*)p;
264      if (c < 0x0080)
265      {
266         m[0] = c;
267      }
268      else if (c < 0x800)
269      {
270         m[0] = 0xC0 | (c >> 6);
271         m[1] = 0x80 | (c & 0x3f);
272      }
273      else if (c < 0x10000)
274      {
275         m[0] = 0xE0 | (c >> 12);
276         m[1] = 0x80 | ((c>>6) & 0x3f);
277         m[2] = 0x80 | (c & 0x3f);
278      }
279      else /* U+10000 U+1FFFFF */
280      {
281         m[0] = 0xF0 | (c >> 18);
282         m[1] = 0x80 | ((c>>12) & 0x3f);
283         m[2] = 0x80 | ((c>>6) & 0x3f);
284         m[3] = 0x80 | (c & 0x3f);
285      }
286   }
287   static const mem_t *nthcode(const mem_t *p, const unsigned n)
288   {
289      const mem_t *p1 = p;
290      int i = n;
291      while (i-- > 0)
292         p1 += codelen(p1);
293      return p1;
294   }
295};
296
297struct pstring : public pstring_t<putf8_traits>
298{
299public:
300
301   typedef pstring_t<putf8_traits> type_t;
302
303   // simple construction/destruction
304   pstring() : type_t() { }
305
306   // construction with copy
307   pstring(const mem_t *string) : type_t(string) { }
308   pstring(const type_t &string) : type_t(string) { }
309
310   const type_t vprintf(va_list args) const;
311   static const type_t sprintf(const char *format, ...) ATTR_PRINTF(1,2);
312
313};
314
315// ----------------------------------------------------------------------------------------
316// pstringbuffer: a string buffer implementation
317//
318// string buffer are optimized to handle concatenations. This implementation is designed
319// to specifically interact with pstrings nicely.
320// ----------------------------------------------------------------------------------------
321
322struct pstringbuffer
323{
324public:
325
326   static const int DEFAULT_SIZE = 2048;
327   // simple construction/destruction
328   pstringbuffer()
329   {
330      init();
331      resize(DEFAULT_SIZE);
332   }
333
334   ~pstringbuffer();
335
336   // construction with copy
337   pstringbuffer(const char *string) {init(); if (string != NULL) pcopy(string); }
338   pstringbuffer(const pstring &string) {init(); pcopy(string); }
339
340   // assignment operators
341   pstringbuffer &operator=(const char *string) { pcopy(string); return *this; }
342   pstringbuffer &operator=(const pstring &string) { pcopy(string); return *this; }
343   pstringbuffer &operator=(const pstringbuffer &string) { pcopy(string); return *this; }
344
345   // C string conversion helpers
346   const char *cstr() const { return m_ptr; }
347
348   operator pstring() const { return pstring(m_ptr); }
349
350   // concatenation operators
351   pstringbuffer& operator+=(const UINT8 c) { UINT8 buf[2] = { c, 0 }; pcat((char *) buf); return *this; }
352   pstringbuffer& operator+=(const pstring &string) { pcat(string); return *this; }
353   pstringbuffer& operator+=(const char *string) { pcat(string); return *this; }
354
355   std::size_t len() const { return m_len; }
356
357   void cat(const pstring &s) { pcat(s); }
358   void cat(const char *s) { pcat(s); }
359   void cat(const void *m, unsigned l) { pcat(m, l); }
360
361private:
362
363   void init()
364   {
365      m_ptr = NULL;
366      m_size = 0;
367      m_len = 0;
368   }
369
370   void resize(const std::size_t size);
371
372   void pcopy(const char *from);
373   void pcopy(const pstring &from);
374   void pcat(const char *s);
375   void pcat(const pstring &s);
376   void pcat(const void *m, unsigned l);
377
378   char *m_ptr;
379   std::size_t m_size;
380   std::size_t m_len;
381
382};
383
384template <typename T>
385struct ptype_treats
386{
387};
388
389template<>
390struct ptype_treats<char>
391{
392   static short cast(char x) { return x; }
393   static const bool is_signed = true;
394   static const char *size_specifier() { return "h"; }
395};
396
397template<>
398struct ptype_treats<short>
399{
400   static short cast(short x) { return x; }
401   static const bool is_signed = true;
402   static const char *size_specifier() { return "h"; }
403};
404
405template<>
406struct ptype_treats<int>
407{
408   static int cast(int x) { return x; }
409   static const bool is_signed = true;
410   static const char *size_specifier() { return ""; }
411};
412
413template<>
414struct ptype_treats<long>
415{
416   static long cast(long x) { return x; }
417   static const bool is_signed = true;
418   static const char *size_specifier() { return "l"; }
419};
420
421template<>
422struct ptype_treats<long long>
423{
424   static long long cast(long long x) { return x; }
425   static const bool is_signed = true;
426   static const char *size_specifier() { return "ll"; }
427};
428
429template<>
430struct ptype_treats<unsigned char>
431{
432   static unsigned short cast(unsigned char x) { return x; }
433   static const bool is_signed = false;
434   static const char *size_specifier() { return "h"; }
435};
436
437template<>
438struct ptype_treats<unsigned short>
439{
440   static unsigned short cast(unsigned short x) { return x; }
441   static const bool is_signed = false;
442   static const char *size_specifier() { return "h"; }
443};
444
445template<>
446struct ptype_treats<unsigned int>
447{
448   static unsigned int cast(unsigned int x) { return x; }
449   static const bool is_signed = false;
450   static const char *size_specifier() { return ""; }
451};
452
453template<>
454struct ptype_treats<unsigned long>
455{
456   static unsigned long cast(unsigned long x) { return x; }
457   static const bool is_signed = false;
458   static const char *size_specifier() { return "l"; }
459};
460
461template<>
462struct ptype_treats<unsigned long long>
463{
464   static unsigned long long cast(unsigned long long x) { return x; }
465   static const bool is_signed = false;
466   static const char *size_specifier() { return "ll"; }
467};
468
469template <typename P>
470class pformat_base
471{
472public:
473
474   virtual ~pformat_base() { }
475
476   ATTR_COLD P &operator ()(const double x, const char *f = "") { format_element(f, "", "f", x); return static_cast<P &>(*this); }
477   ATTR_COLD P &          e(const double x, const char *f = "") { format_element(f, "", "e", x); return static_cast<P &>(*this);  }
478   ATTR_COLD P &          g(const double x, const char *f = "") { format_element(f, "", "g", x); return static_cast<P &>(*this);  }
479
480   ATTR_COLD P &operator ()(const char *x, const char *f = "") { format_element(f, "", "s", x); return static_cast<P &>(*this);  }
481   ATTR_COLD P &operator ()(char *x, const char *f = "") { format_element(f, "", "s", x); return static_cast<P &>(*this);  }
482   ATTR_COLD P &operator ()(const void *x, const char *f = "") { format_element(f, "", "p", x); return static_cast<P &>(*this);  }
483   ATTR_COLD P &operator ()(const pstring &x, const char *f = "") { format_element(f, "", "s", x.cstr() ); return static_cast<P &>(*this);  }
484
485   template<typename T>
486   ATTR_COLD P &operator ()(const T x, const char *f = "")
487   {
488      if (ptype_treats<T>::is_signed)
489         format_element(f, ptype_treats<T>::size_specifier(), "d", ptype_treats<T>::cast(x));
490      else
491         format_element(f, ptype_treats<T>::size_specifier(), "u", ptype_treats<T>::cast(x));
492      return static_cast<P &>(*this);
493   }
494
495   template<typename T>
496   ATTR_COLD P &x(const T x, const char *f = "")
497   {
498      format_element(f, ptype_treats<T>::size_specifier(), "x", x);
499      return static_cast<P &>(*this);
500   }
501
502   template<typename T>
503   ATTR_COLD P &o(const T x, const char *f = "")
504   {
505      format_element(f, ptype_treats<T>::size_specifier(), "o", x);
506      return static_cast<P &>(*this);
507   }
508
509protected:
510
511   virtual void format_element(const char *f, const char *l, const char *fmt_spec, ...) = 0;
512
513};
514
515class pfmt : public pformat_base<pfmt>
516{
517public:
518   ATTR_COLD pfmt(const pstring &fmt);
519   ATTR_COLD pfmt(const char *fmt);
520
521   operator pstring() const { return m_str; }
522
523   const char *cstr() { return m_str; }
524
525
526protected:
527   void format_element(const char *f, const char *l, const char *fmt_spec, ...);
528
529private:
530
531   char m_str[2048];
532   unsigned m_arg;
533};
534
535enum plog_level
536{
537   DEBUG,
538   INFO,
539   VERBOSE,
540   WARNING,
541   ERROR,
542   FATAL
543};
544
545class plog_dispatch_intf;
546
547template <bool build_enabled = true>
548class pfmt_writer_t
549{
550public:
551   pfmt_writer_t() : m_enabled(true)  { }
552   virtual ~pfmt_writer_t() { }
553
554   ATTR_COLD void operator ()(const char *fmt) const
555   {
556      if (build_enabled && m_enabled) vdowrite(fmt);
557   }
558
559   template<typename T1>
560   ATTR_COLD void operator ()(const char *fmt, const T1 &v1) const
561   {
562      if (build_enabled && m_enabled) vdowrite(pfmt(fmt)(v1));
563   }
564
565   template<typename T1, typename T2>
566   ATTR_COLD void operator ()(const char *fmt, const T1 &v1, const T2 &v2) const
567   {
568      if (build_enabled && m_enabled) vdowrite(pfmt(fmt)(v1)(v2));
569   }
570
571   template<typename T1, typename T2, typename T3>
572   ATTR_COLD void operator ()(const char *fmt, const T1 &v1, const T2 &v2, const T3 &v3) const
573   {
574      if (build_enabled && m_enabled) vdowrite(pfmt(fmt)(v1)(v2)(v3));
575   }
576
577   template<typename T1, typename T2, typename T3, typename T4>
578   ATTR_COLD void operator ()(const char *fmt, const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4) const
579   {
580      if (build_enabled && m_enabled) vdowrite(pfmt(fmt)(v1)(v2)(v3)(v4));
581   }
582
583   template<typename T1, typename T2, typename T3, typename T4, typename T5>
584   ATTR_COLD void operator ()(const char *fmt, const T1 &v1, const T2 &v2, const T3 &v3, const T4 &v4, const T5 &v5) const
585   {
586      if (build_enabled && m_enabled) vdowrite(pfmt(fmt)(v1)(v2)(v3)(v4)(v5));
587   }
588
589   void set_enabled(const bool v)
590   {
591      m_enabled = v;
592   }
593
594   bool is_enabled() const { return m_enabled; }
595
596protected:
597   virtual void vdowrite(const pstring &ls) const {}
598
599private:
600   bool m_enabled;
601
602};
603
604template <plog_level L, bool build_enabled = true>
605class plog_channel : public pfmt_writer_t<build_enabled>
606{
607public:
608   plog_channel(plog_dispatch_intf *b) : pfmt_writer_t<build_enabled>(),  m_base(b) { }
609   virtual ~plog_channel() { }
610
611protected:
612   virtual void vdowrite(const pstring &ls) const;
613
614private:
615   plog_dispatch_intf *m_base;
616};
617
618class plog_dispatch_intf
619{
620   template<plog_level, bool> friend class plog_channel;
621
622public:
623   virtual ~plog_dispatch_intf() { }
624protected:
625   virtual void vlog(const plog_level &l, const pstring &ls) const = 0;
626};
627
628template<bool debug_enabled>
629class plog_base
630{
631public:
632
633   plog_base(plog_dispatch_intf *proxy)
634   : debug(proxy),
635      info(proxy),
636      verbose(proxy),
637      warning(proxy),
638      error(proxy),
639      fatal(proxy)
640   {}
641   virtual ~plog_base() {};
642
643   plog_channel<DEBUG, debug_enabled> debug;
644   plog_channel<INFO> info;
645   plog_channel<VERBOSE> verbose;
646   plog_channel<WARNING> warning;
647   plog_channel<ERROR> error;
648   plog_channel<FATAL> fatal;
649};
650
651
652template <plog_level L, bool build_enabled>
653void plog_channel<L, build_enabled>::vdowrite(const pstring &ls) const
654{
655   m_base->vlog(L, ls);
656}
657
658#endif /* _PSTRING_H_ */
trunk/src/lib/netlist/prg/nltool.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/***************************************************************************
4
5    nltool.c
6
7    Simple tool to debug netlists outside MAME.
8
9****************************************************************************/
10
11#include <cstdio>
12
13#ifdef PSTANDALONE
14#if (PSTANDALONE)
15#define PSTANDALONE_PROVIDED
16#endif
17#endif
18
19#include "plib/poptions.h"
20#include "plib/pstring.h"
21#include "plib/plists.h"
22#include "nl_setup.h"
23#include "nl_factory.h"
24#include "nl_parser.h"
25#include "devices/net_lib.h"
26#include "tools/nl_convert.h"
27
28
29#ifdef PSTANDALONE_PROVIDED
30
31#include <ctime>
32
33#define osd_ticks_t clock_t
34
35inline osd_ticks_t osd_ticks_per_second() { return CLOCKS_PER_SEC; }
36
37osd_ticks_t osd_ticks(void) { return clock(); }
38#else
39
40#endif
41
42/***************************************************************************
43 * MAME COMPATIBILITY ...
44 *
45 * These are needed if we link without libutil
46 ***************************************************************************/
47
48#if 0
49void ATTR_PRINTF(1,2) osd_printf_warning(const char *format, ...)
50{
51   va_list argptr;
52
53   /* do the output */
54   va_start(argptr, format);
55   vprintf(format, argptr);
56   va_end(argptr);
57}
58
59void *malloc_file_line(size_t size, const char *file, int line)
60{
61   // allocate the memory and fail if we can't
62   void *ret = osd_malloc(size);
63   memset(ret, 0, size);
64   return ret;
65}
66
67void *malloc_array_file_line(size_t size, const char *file, int line)
68{
69   // allocate the memory and fail if we can't
70   void *ret = osd_malloc_array(size);
71   memset(ret, 0, size);
72   return ret;
73}
74
75void free_file_line( void *memory, const char *file, int line )
76{
77   osd_free( memory );
78}
79
80void CLIB_DECL logerror(const char *format, ...)
81{
82   va_list arg;
83   va_start(arg, format);
84   vprintf(format, arg);
85   va_end(arg);
86}
87
88void report_bad_cast(const std::type_info &src_type, const std::type_info &dst_type)
89{
90   printf("Error: bad downcast<> or device<>.  Tried to convert a %s to a %s, which are incompatible.\n",
91         src_type.name(), dst_type.name());
92   throw;
93}
94#endif
95
96class tool_options_t : public poptions
97{
98public:
99   tool_options_t() :
100      poptions(),
101      opt_ttr ("t", "time_to_run", 1.0,   "time to run the emulation (seconds)", this),
102      opt_name("n", "name",        "",      "netlist in file to run; default is first one", this),
103      opt_logs("l", "logs",        "",      "colon separated list of terminals to log", this),
104      opt_file("f", "file",        "-",     "file to process (default is stdin)", this),
105      opt_type("y", "type",        "spice", "spice:eagle", "type of file to be converted: spice,eagle", this),
106      opt_cmd ("c", "cmd",         "run",   "run|convert|listdevices", this),
107      opt_inp( "i", "input",       "",      "input file to process (default is none)", this),
108      opt_verb("v", "verbose",              "be verbose - this produces lots of output", this),
109      opt_quiet("q", "quiet",               "be quiet - no warnings", this),
110      opt_help("h", "help",                 "display help", this)
111   {}
112
113   poption_double opt_ttr;
114   poption_str    opt_name;
115   poption_str    opt_logs;
116   poption_str    opt_file;
117   poption_str_limit opt_type;
118   poption_str    opt_cmd;
119   poption_str    opt_inp;
120   poption_bool   opt_verb;
121   poption_bool   opt_quiet;
122   poption_bool   opt_help;
123};
124
125//Alternative
126//static poption *optlist[] = { &opt_ttr, &opt_logs, &opt_file, &opt_cmd, &opt_verb, &opt_help, NULL };
127
128NETLIST_START(dummy)
129   /* Standard stuff */
130
131   CLOCK(clk, 1000) // 1000 Hz
132   SOLVER(Solver, 48000)
133
134NETLIST_END()
135
136/***************************************************************************
137    CORE IMPLEMENTATION
138***************************************************************************/
139
140pstring filetobuf(pstring fname)
141{
142   pstring pbuf = "";
143
144   if (fname == "-")
145   {
146      char lbuf[1024];
147      while (!feof(stdin))
148      {
149         fgets(lbuf, 1024, stdin);
150         pbuf += lbuf;
151      }
152      printf("%d\n",*(pbuf.right(1).cstr()+1));
153      return pbuf;
154   }
155   else
156   {
157      FILE *f;
158      f = fopen(fname.cstr(), "rb");
159      fseek(f, 0, SEEK_END);
160      long fsize = ftell(f);
161      fseek(f, 0, SEEK_SET);
162
163      char *buf = (char *) malloc(fsize + 1);
164      fread(buf, fsize, 1, f);
165      buf[fsize] = 0;
166      fclose(f);
167      pbuf = buf;
168      free(buf);
169      return pbuf;
170   }
171}
172
173class netlist_tool_t : public netlist::netlist_t
174{
175public:
176
177   netlist_tool_t()
178   : netlist::netlist_t(), m_opts(NULL), m_setup(NULL)
179   {
180   }
181
182   ~netlist_tool_t()
183   {
184      if (m_setup != NULL)
185         pfree(m_setup);
186   };
187
188   void init()
189   {
190      m_setup = palloc(netlist::setup_t(this));
191      this->init_object(*this, "netlist");
192      m_setup->init();
193   }
194
195   void read_netlist(const pstring &filename, const pstring &name)
196   {
197      // read the netlist ...
198
199      m_setup->register_source(palloc(netlist::source_file_t(filename)));
200      m_setup->include(name);
201      log_setup();
202
203      // start devices
204      m_setup->start_devices();
205      m_setup->resolve_inputs();
206      // reset
207      this->reset();
208   }
209
210   void log_setup()
211   {
212      log().debug("Creating dynamic logs ...\n");
213      pstring_list_t ll(m_opts ? m_opts->opt_logs() : "" , ":");
214      for (unsigned i=0; i < ll.size(); i++)
215      {
216         pstring name = "log_" + ll[i];
217         /*netlist_device_t *nc = */ m_setup->register_dev("LOG", name);
218         m_setup->register_link(name + ".I", ll[i]);
219      }
220   }
221
222   tool_options_t *m_opts;
223
224protected:
225
226   void vlog(const plog_level &l, const pstring &ls) const
227   {
228      switch (l)
229      {
230         case DEBUG:
231         case INFO:
232            break;
233         case VERBOSE:
234            if (m_opts ? m_opts->opt_verb() : false)
235            {
236               printf("%s\n", ls.cstr());
237            }
238            break;
239         case WARNING:
240            if (!(m_opts ? m_opts->opt_quiet() : false))
241            {
242               printf("%s\n", ls.cstr());
243            }
244            break;
245         case ERROR:
246            printf("%s\n", ls.cstr());
247            break;
248         case FATAL:
249            printf("%s\n", ls.cstr());
250            throw;
251      }
252   }
253
254private:
255   netlist::setup_t *m_setup;
256};
257
258
259void usage(tool_options_t &opts)
260{
261   fprintf(stderr,
262      "Usage:\n"
263      "  nltool -help\n"
264      "  nltool [options]\n"
265      "\n"
266      "Where:\n"
267   );
268   fprintf(stderr, "%s\n", opts.help().cstr());
269}
270
271struct input_t
272{
273   input_t()
274   : m_param(NULL), m_value(0.0)
275   {
276   }
277   input_t(netlist::netlist_t *netlist, const pstring &line)
278   {
279      char buf[400];
280      double t;
281      int e = sscanf(line.cstr(), "%lf,%[^,],%lf", &t, buf, &m_value);
282      if ( e!= 3)
283         throw netlist::fatalerror_e(pfmt("error {1} scanning line {2}\n")(e)(line));
284      m_time = netlist::netlist_time::from_double(t);
285      m_param = netlist->setup().find_param(buf, true);
286   }
287
288   void setparam()
289   {
290      switch (m_param->param_type())
291      {
292         case netlist::param_t::MODEL:
293         case netlist::param_t::STRING:
294            throw netlist::fatalerror_e(pfmt("param {1} is not numeric\n")(m_param->name()));
295         case netlist::param_t::DOUBLE:
296            static_cast<netlist::param_double_t*>(m_param)->setTo(m_value);
297            break;
298         case netlist::param_t::INTEGER:
299            static_cast<netlist::param_int_t*>(m_param)->setTo((int)m_value);
300            break;
301         case netlist::param_t::LOGIC:
302            static_cast<netlist::param_logic_t*>(m_param)->setTo((int) m_value);
303            break;
304      }
305   }
306
307   netlist::netlist_time m_time;
308   netlist::param_t *m_param;
309   double m_value;
310
311};
312
313plist_t<input_t> *read_input(netlist::netlist_t *netlist, pstring fname)
314{
315   plist_t<input_t> *ret = palloc(plist_t<input_t>());
316   if (fname != "")
317   {
318      pifilestream f(fname);
319      pstring l;
320      while (f.readline(l))
321      {
322         if (l != "")
323         {
324            input_t inp(netlist, l);
325            ret->add(inp);
326         }
327      }
328   }
329   return ret;
330}
331
332static void run(tool_options_t &opts)
333{
334   netlist_tool_t nt;
335   osd_ticks_t t = osd_ticks();
336
337   nt.m_opts = &opts;
338   nt.init();
339   nt.read_netlist(opts.opt_file(), opts.opt_name());
340
341   plist_t<input_t> *inps = read_input(&nt, opts.opt_inp());
342
343   double ttr = opts.opt_ttr();
344
345   printf("startup time ==> %5.3f\n", (double) (osd_ticks() - t) / (double) osd_ticks_per_second() );
346   printf("runnning ...\n");
347   t = osd_ticks();
348
349   unsigned pos = 0;
350   netlist::netlist_time nlt = netlist::netlist_time::zero;
351
352   while (pos < inps->size() && (*inps)[pos].m_time < netlist::netlist_time::from_double(ttr))
353   {
354      nt.process_queue((*inps)[pos].m_time - nlt);
355      (*inps)[pos].setparam();
356      nlt = (*inps)[pos].m_time;
357      pos++;
358   }
359   nt.process_queue(netlist::netlist_time::from_double(ttr) - nlt);
360   nt.stop();
361   pfree(inps);
362
363   double emutime = (double) (osd_ticks() - t) / (double) osd_ticks_per_second();
364   printf("%f seconds emulation took %f real time ==> %5.2f%%\n", ttr, emutime, ttr/emutime*100.0);
365}
366
367/*-------------------------------------------------
368    listdevices - list all known devices
369-------------------------------------------------*/
370
371static void listdevices()
372{
373   netlist_tool_t nt;
374   nt.init();
375   const netlist::factory_list_t &list = nt.setup().factory();
376
377   nt.setup().register_source(palloc(netlist::source_proc_t("dummy", &netlist_dummy)));
378   nt.setup().include("dummy");
379
380   nt.setup().start_devices();
381   nt.setup().resolve_inputs();
382
383   for (unsigned i=0; i < list.size(); i++)
384   {
385      netlist::base_factory_t *f = list.value_at(i);
386      pstring out = pfmt("{1} {2}(<id>")(f->classname(),"-20")(f->name());
387      pstring terms("");
388
389      netlist::device_t *d = f->Create();
390      d->init(nt, pfmt("dummy{1}")(i));
391      d->start_dev();
392
393      // get the list of terminals ...
394      for (unsigned j=0; j < d->m_terminals.size(); j++)
395      {
396         pstring inp = d->m_terminals[j];
397         if (inp.startsWith(d->name() + "."))
398            inp = inp.substr(d->name().len() + 1);
399         terms += "," + inp;
400      }
401
402      if (f->param_desc().startsWith("+"))
403      {
404         out += "," + f->param_desc().substr(1);
405         terms = "";
406      }
407      else if (f->param_desc() == "-")
408      {
409         /* no params at all */
410      }
411      else
412      {
413         out += "," + f->param_desc();
414      }
415      out += ")";
416      printf("%s\n", out.cstr());
417      if (terms != "")
418         printf("Terminals: %s\n", terms.substr(1).cstr());
419   }
420}
421
422
423
424/*-------------------------------------------------
425    main - primary entry point
426-------------------------------------------------*/
427
428#if (!PSTANDALONE)
429#include "corealloc.h"
430#endif
431
432static const char *pmf_verbose[] =
433{
434   "NL_PMF_TYPE_VIRTUAL",
435   "NL_PMF_TYPE_GNUC_PMF",
436   "NL_PMF_TYPE_GNUC_PMF_CONV",
437   "NL_PMF_TYPE_INTERNAL"
438};
439
440int main(int argc, char *argv[])
441{
442#if (!PSTANDALONE)
443   track_memory(true);
444   {
445#endif
446   tool_options_t opts;
447   int ret;
448
449   fprintf(stderr, "%s", "WARNING: This is Work In Progress! - It may fail anytime\n");
450   fprintf(stderr, "Update dispatching using method %s\n", pmf_verbose[NL_PMF_TYPE]);
451   if ((ret = opts.parse(argc, argv)) != argc)
452   {
453      fprintf(stderr, "Error parsing %s\n", argv[ret]);
454      usage(opts);
455      return 1;
456   }
457
458   if (opts.opt_help())
459   {
460      usage(opts);
461      return 1;
462   }
463
464   pstring cmd = opts.opt_cmd();
465   if (cmd == "listdevices")
466      listdevices();
467   else if (cmd == "run")
468      run(opts);
469   else if (cmd == "convert")
470   {
471      pstring contents = filetobuf(opts.opt_file());
472      nl_convert_base_t *converter = NULL;
473      if (opts.opt_type().equals("spice"))
474         converter = palloc(nl_convert_spice_t);
475      else
476         converter = palloc(nl_convert_eagle_t);
477      converter->convert(contents);
478      /* present result */
479      printf("%s\n", converter->result().cstr());
480      pfree(converter);
481   }
482   else
483   {
484      fprintf(stderr, "Unknown command %s\n", cmd.cstr());
485      usage(opts);
486      return 1;
487   }
488#if (!PSTANDALONE)
489   }
490   dump_unfreed_mem();
491#endif
492   return 0;
493}
trunk/src/lib/netlist/prg/nlwav.c
r0r249195
1#include <cstdio>
2#include <cstring>
3#include "plib/poptions.h"
4#include "plib/pstring.h"
5#include "plib/plists.h"
6#include "plib/pstream.h"
7#include "nl_setup.h"
8
9class nlwav_options_t : public poptions
10{
11public:
12   nlwav_options_t() :
13      poptions(),
14#if 0
15      opt_ttr ("t", "time_to_run", 1.0,     "time to run the emulation (seconds)", this),
16      opt_name("n", "name",        "",      "netlist in file to run; default is first one", this),
17      opt_logs("l", "logs",        "",      "colon separated list of terminals to log", this),
18      opt_file("f", "file",        "-",     "file to process (default is stdin)", this),
19      opt_type("y", "type",        "spice", "spice:eagle", "type of file to be converted: spice,eagle", this),
20      opt_cmd ("c", "cmd",         "run",   "run|convert|listdevices", this),
21      opt_inp( "i", "input",       "",      "input file to process (default is none)", this),
22#endif
23      opt_inp( "i", "input",       "",      "input file", this),
24      opt_out( "o", "output",      "",      "output file", this),
25      opt_amp( "a", "amp",    10000.0,      "amplification after mean correction", this),
26      opt_verb("v", "verbose",              "be verbose - this produces lots of output", this),
27      opt_quiet("q", "quiet",               "be quiet - no warnings", this),
28      opt_help("h", "help",                 "display help", this)
29   {}
30#if 0
31   poption_double opt_ttr;
32   poption_str    opt_name;
33   poption_str    opt_logs;
34   poption_str    opt_file;
35   poption_str_limit opt_type;
36   poption_str    opt_cmd;
37#endif
38   poption_str    opt_inp;
39   poption_str    opt_out;
40   poption_double opt_amp;
41   poption_bool   opt_verb;
42   poption_bool   opt_quiet;
43   poption_bool   opt_help;
44};
45
46/* http://de.wikipedia.org/wiki/RIFF_WAVE */
47class wav_t
48{
49public:
50   wav_t(postream &strm, unsigned sr) : m_f(strm)
51   {
52//      m_f = strm;
53      initialize(sr);
54      m_f.write(&m_fh, sizeof(m_fh));
55      m_f.write(&m_fmt, sizeof(m_fmt));
56      m_f.write(&m_data, sizeof(m_data));
57   }
58   ~wav_t()
59   {
60      close();
61   }
62
63   unsigned channels() { return m_fmt.channels; }
64   unsigned sample_rate() { return m_fmt.sample_rate; }
65
66   void write_sample(int sample)
67   {
68      m_data.len += m_fmt.block_align;
69      short ps = sample; /* 16 bit sample, FIXME: powerpc? */
70      m_f.write(&ps, sizeof(ps));
71   }
72
73   void close()
74   {
75      m_f.seek(0);
76      m_f.write(&m_fh, sizeof(m_fh));
77      m_f.write(&m_fmt, sizeof(m_fmt));
78
79      //data.len = fmt.block_align * n;
80      m_f.write(&m_data, sizeof(m_data));
81   }
82private:
83   struct riff_chunk_t
84   {
85      char        group_id[4];
86      unsigned    filelen;
87      char        rifftype[4];
88   };
89
90   struct riff_format_t
91   {
92      char        signature[4];
93      unsigned    fmt_length;
94      short       format_tag;
95      short       channels;
96      unsigned    sample_rate;
97      unsigned    bytes_per_second;
98      short       block_align;
99      short       bits_sample;
100   };
101
102   struct riff_data_t
103   {
104      char        signature[4];
105      unsigned    len;
106      // data follows
107   };
108
109   void initialize(unsigned sr)
110   {
111      std::strncpy(m_fh.group_id, "RIFF", 4);
112      m_fh.filelen = 0; // Fixme
113      std::strncpy(m_fh.rifftype, "WAVE", 4);
114
115      std::strncpy(m_fmt.signature, "fmt ", 4);
116      m_fmt.fmt_length = 16;
117      m_fmt.format_tag = 0x0001; //PCM
118      m_fmt.channels = 1;
119      m_fmt.sample_rate = sr;
120      m_fmt.bits_sample = 16;
121      m_fmt.block_align = m_fmt.channels * ((m_fmt.bits_sample + 7) / 8);
122      m_fmt.bytes_per_second = m_fmt.sample_rate * m_fmt.block_align;
123
124      std::strncpy(m_data.signature, "data", 4);
125      m_data.len = m_fmt.bytes_per_second * 2 * 0;
126
127   }
128
129   riff_chunk_t m_fh;
130   riff_format_t m_fmt;
131   riff_data_t m_data;
132
133   postream &m_f;
134
135};
136
137void convert(nlwav_options_t &opts)
138{
139   pofilestream fo(opts.opt_out());
140   if (fo.bad())
141   {
142      throw netlist::fatalerror_e("Error opening output file: " + opts.opt_out());
143   }
144   wav_t wo(fo, 48000);
145
146   pifilestream fin(opts.opt_inp());
147   if (fin.bad())
148      throw netlist::fatalerror_e("Error opening input file: " + opts.opt_inp());
149
150   double dt = 1.0 / (double) wo.sample_rate();
151   double ct = dt;
152   //double mean = 2.4;
153   double amp = opts.opt_amp();
154   double mean = 0.0;
155   double means = 0.0;
156   double cursam = 0.0;
157   double outsam = 0.0;
158   double lt = 0.0;
159   double maxsam = -1e9;
160   double minsam = 1e9;
161   int n = 0;
162   //short sample = 0;
163   pstring line;
164
165   while(fin.readline(line))
166   {
167#if 1
168      float t = 0.0; float v = 0.0;
169      sscanf(line.cstr(), "%f %f", &t, &v);
170      while (t >= ct)
171      {
172         outsam += (ct - lt) * cursam;
173         outsam = outsam / dt;
174         if (t>0.0)
175         {
176            means += outsam;
177            maxsam = std::max(maxsam, outsam);
178            minsam = std::min(minsam, outsam);
179            n++;
180            //mean = means / (double) n;
181            mean += 5.0 / (double) wo.sample_rate() * (outsam - mean);
182         }
183         outsam = (outsam - mean) * amp;
184         outsam = std::max(-32000.0, outsam);
185         outsam = std::min(32000.0, outsam);
186         wo.write_sample((int) outsam);
187         outsam = 0.0;
188         lt = ct;
189         ct += dt;
190      }
191      outsam += (t-lt)*cursam;
192      lt = t;
193      cursam = v;
194#else
195      float t = 0.0; float v = 0.0;
196      fscanf(FIN, "%f %f", &t, &v);
197      while (ct <= t)
198      {
199         wo.write_sample(sample);
200         n++;
201         ct += dt;
202      }
203      means += v;
204      mean = means / (double) n;
205      v = v - mean;
206      v = v * amp;
207      if (v>32000.0)
208         v = 32000.0;
209      else if (v<-32000.0)
210         v = -32000.0;
211      sample = v;
212      //printf("%f %f\n", t, v);
213#endif
214   }
215   printf("Mean (low freq filter): %f\n", mean);
216   printf("Mean (static):          %f\n", means / (double) n);
217   printf("Amp + %f\n", 32000.0 / (maxsam- mean));
218   printf("Amp - %f\n", -32000.0 / (minsam- mean));
219   wo.close();
220   fo.close();
221   fin.close();
222
223}
224
225void usage(nlwav_options_t &opts)
226{
227   fprintf(stderr,
228      "Usage:\n"
229      "  nltool -help\n"
230      "  nltool [options]\n"
231      "\n"
232      "Where:\n"
233   );
234   fprintf(stderr, "%s\n", opts.help().cstr());
235}
236
237
238int main(int argc, char *argv[])
239{
240#if (!PSTANDALONE)
241   track_memory(true);
242   {
243#endif
244   nlwav_options_t opts;
245   int ret;
246
247   if ((ret = opts.parse(argc, argv)) != argc)
248   {
249      fprintf(stderr, "Error parsing %s\n", argv[ret]);
250      usage(opts);
251      return 1;
252   }
253
254   if (opts.opt_help())
255   {
256      usage(opts);
257      return 1;
258   }
259
260   convert(opts);
261#if (!PSTANDALONE)
262   }
263   dump_unfreed_mem();
264#endif
265
266   return 0;
267}
268
269/*
270Der Daten-Abschnitt enth??lt die Abtastwerte:
271Offset  L??nge  Inhalt  Beschreibung
27236 (0x24)   4   'data'  Header-Signatur
27340 (0x28)   4   <length>    L??nge des Datenblocks, max. <Dateigr????e>?????????44
274
2750 (0x00)    char    4   'RIFF'
2764 (0x04)    unsigned    4   <Dateigr????e>?????????8
2778 (0x08)    char    4   'WAVE'
278
279Der fmt-Abschnitt (24 Byte) beschreibt das Format der einzelnen Abtastwerte:
280Offset  L??nge  Inhalt  Beschreibung
28112 (0x0C)   4   'fmt '  Header-Signatur (folgendes Leerzeichen beachten)
28216 (0x10)   4   <fmt length>    L??nge des restlichen fmt-Headers (16 Bytes)
28320 (0x14)   2   <format tag>    Datenformat der Abtastwerte (siehe separate Tabelle weiter unten)
28422 (0x16)   2   <channels>  Anzahl der Kan??le: 1 = mono, 2 = stereo; mittlerweile sind auch mehr als 2 Kan??le (z. B. f??r Raumklang) m??glich.[2]
28524 (0x18)   4   <sample rate>   Samples pro Sekunde je Kanal (z. B. 44100)
28628 (0x1C)   4   <bytes/second>  Abtastrate????????Frame-Gr????e
28732 (0x20)   2   <block align>   Frame-Gr????e = <Anzahl der Kan??le>????????((<Bits/Sample (eines Kanals)>???+???7)???/???8)   (Division ohne Rest)
28834 (0x22)   2   <bits/sample>   Anzahl der Datenbits pro Samplewert je Kanal (z. B. 12)
289*/
trunk/src/lib/netlist/solver/mat_cr.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * mat_cr.h
5 *
6 * Compressed row format matrices
7 *
8 */
9
10#ifndef MAT_CR_H_
11#define MAT_CR_H_
12
13#include <algorithm>
14#include "plib/pconfig.h"
15
16template<int _storage_N>
17struct mat_cr_t
18{
19   unsigned nz_num;
20   unsigned ia[_storage_N + 1];
21   unsigned ja[_storage_N * _storage_N];
22   unsigned diag[_storage_N];       /* n */
23
24   template<typename T>
25   void mult_vec(const T * RESTRICT A, const T * RESTRICT x, T * RESTRICT res)
26   {
27      /*
28       * res = A * x
29       */
30
31      unsigned i = 0;
32      unsigned k = 0;
33      const unsigned oe = nz_num;
34
35      while (k < oe)
36      {
37         double tmp = 0.0;
38         const unsigned e = ia[i+1];
39         for (; k < e; k++)
40            tmp += A[k] * x[ja[k]];
41         res[i++] = tmp;
42      }
43   }
44
45   void incomplete_LU_factorization(const nl_double * RESTRICT A, nl_double * RESTRICT LU)
46   {
47      /*
48       * incomplete LU Factorization according to http://de.wikipedia.org/wiki/ILU-Zerlegung
49       *
50       * Result is stored in matrix LU
51       *
52       */
53
54      const unsigned lnz = nz_num;
55
56      for (unsigned k = 0; k < lnz; k++)
57         LU[k] = A[k];
58
59      for (unsigned i = 1; ia[i] < lnz; i++) // row i
60      {
61         const unsigned iai1 = ia[i + 1];
62         for (unsigned pk = ia[i]; pk < diag[i]; pk++) // all columns left of diag in row i
63         {
64            // pk == (i, k)
65            const unsigned k = ja[pk];
66            const unsigned iak1 = ia[k + 1];
67            const double LUpk = LU[pk] = LU[pk] / LU[diag[k]];
68
69            unsigned pt = ia[k];
70
71            for (unsigned pj = pk + 1; pj < iai1; pj++)  // pj = (i, j)
72            {
73               // we can assume that within a row ja increases continuously */
74               const unsigned ej = ja[pj];
75               while (ja[pt] < ej && pt < iak1)
76                  pt++;
77               if (pt < iak1 && ja[pt] == ej)
78                  LU[pj] = LU[pj] - LUpk * LU[pt];
79            }
80         }
81      }
82   }
83
84   void solveLUx (const nl_double * RESTRICT LU, nl_double * RESTRICT r)
85   {
86      /*
87       * Solve a linear equation Ax = r
88       * where
89       *      A = L*U
90       *
91       *      L unit lower triangular
92       *      U upper triangular
93       *
94       * ==> LUx = r
95       *
96       * ==> Ux = L?????r = w
97       *
98       * ==> r = Lw
99       *
100       * This can be solved for w using backwards elimination in L.
101       *
102       * Now Ux = w
103       *
104       * This can be solved for x using backwards elimination in U.
105       *
106       */
107
108      unsigned i;
109
110      for (i = 1; ia[i] < nz_num; i++ )
111      {
112         double tmp = 0.0;
113         const unsigned j1 = ia[i];
114         const unsigned j2 = diag[i];
115
116         for (unsigned j = j1; j < j2; j++ )
117            tmp +=  LU[j] * r[ja[j]];
118
119         r[i] -= tmp;
120      }
121      // i now is equal to n;
122      for (; 0 < i; i-- )
123      {
124         const unsigned im1 = i - 1;
125         double tmp = 0.0;
126         const unsigned j1 = diag[im1] + 1;
127         const unsigned j2 = ia[im1+1];
128         for (unsigned j = j1; j < j2; j++ )
129            tmp += LU[j] * r[ja[j]];
130         r[im1] = (r[im1] - tmp) / LU[diag[im1]];
131      }
132   }
133
134};
135
136#endif /* MAT_CR_H_ */
trunk/src/lib/netlist/solver/nld_ms_direct.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_ms_direct.h
5 *
6 */
7
8#ifndef NLD_MS_DIRECT_H_
9#define NLD_MS_DIRECT_H_
10
11#include <algorithm>
12
13#include "solver/nld_solver.h"
14
15NETLIB_NAMESPACE_DEVICES_START()
16
17//#define nl_ext_double __float128 // slow, very slow
18//#define nl_ext_double long double // slightly slower
19#define nl_ext_double double
20
21template <unsigned m_N, unsigned _storage_N>
22class matrix_solver_direct_t: public matrix_solver_t
23{
24public:
25
26   matrix_solver_direct_t(const solver_parameters_t *params, const int size);
27   matrix_solver_direct_t(const eSolverType type, const solver_parameters_t *params, const int size);
28
29   virtual ~matrix_solver_direct_t();
30
31   virtual void vsetup(analog_net_t::list_t &nets);
32   virtual void reset() { matrix_solver_t::reset(); }
33
34   ATTR_HOT inline unsigned N() const { if (m_N == 0) return m_dim; else return m_N; }
35
36   ATTR_HOT inline int vsolve_non_dynamic(const bool newton_raphson);
37
38protected:
39   virtual void add_term(int net_idx, terminal_t *term);
40
41   ATTR_HOT virtual nl_double vsolve();
42
43   ATTR_HOT int solve_non_dynamic(const bool newton_raphson);
44   ATTR_HOT void build_LE_A();
45   ATTR_HOT void build_LE_RHS(nl_double * RESTRICT rhs);
46   ATTR_HOT void LE_solve();
47   ATTR_HOT void LE_back_subst(nl_double * RESTRICT x);
48
49   /* Full LU back substitution, not used currently, in for future use */
50
51   ATTR_HOT void LE_back_subst_full(nl_double * RESTRICT x);
52
53   ATTR_HOT nl_double delta(const nl_double * RESTRICT V);
54   ATTR_HOT void store(const nl_double * RESTRICT V);
55
56   /* bring the whole system to the current time
57    * Don't schedule a new calculation time. The recalculation has to be
58    * triggered by the caller after the netlist element was changed.
59    */
60   ATTR_HOT nl_double compute_next_timestep();
61
62   template <typename T1, typename T2>
63   inline nl_ext_double &A(const T1 r, const T2 c) { return m_A[r][c]; }
64
65   ATTR_ALIGN nl_double m_RHS[_storage_N];
66   ATTR_ALIGN nl_double m_last_RHS[_storage_N]; // right hand side - contains currents
67   ATTR_ALIGN nl_double m_last_V[_storage_N];
68
69   terms_t **m_terms;
70   terms_t *m_rails_temp;
71
72private:
73   ATTR_ALIGN nl_ext_double m_A[_storage_N][((_storage_N + 7) / 8) * 8];
74
75   const unsigned m_dim;
76};
77
78// ----------------------------------------------------------------------------------------
79// matrix_solver_direct
80// ----------------------------------------------------------------------------------------
81
82template <unsigned m_N, unsigned _storage_N>
83matrix_solver_direct_t<m_N, _storage_N>::~matrix_solver_direct_t()
84{
85   for (unsigned k = 0; k < N(); k++)
86   {
87      pfree(m_terms[k]);
88   }
89   pfree_array(m_terms);
90   pfree_array(m_rails_temp);
91}
92
93template <unsigned m_N, unsigned _storage_N>
94ATTR_HOT nl_double matrix_solver_direct_t<m_N, _storage_N>::compute_next_timestep()
95{
96   nl_double new_solver_timestep = m_params.m_max_timestep;
97
98   if (m_params.m_dynamic)
99   {
100      /*
101       * FIXME: We should extend the logic to use either all nets or
102       *        only output nets.
103       */
104      for (unsigned k = 0, iN=N(); k < iN; k++)
105      {
106         analog_net_t *n = m_nets[k];
107
108         const nl_double DD_n = (n->m_cur_Analog - m_last_V[k]);
109         const nl_double hn = current_timestep();
110
111         nl_double DD2 = (DD_n / hn - n->m_DD_n_m_1 / n->m_h_n_m_1) / (hn + n->m_h_n_m_1);
112         nl_double new_net_timestep;
113
114         n->m_h_n_m_1 = hn;
115         n->m_DD_n_m_1 = DD_n;
116         if (nl_math::abs(DD2) > NL_FCONST(1e-30)) // avoid div-by-zero
117            new_net_timestep = nl_math::sqrt(m_params.m_lte / nl_math::abs(NL_FCONST(0.5)*DD2));
118         else
119            new_net_timestep = m_params.m_max_timestep;
120
121         if (new_net_timestep < new_solver_timestep)
122            new_solver_timestep = new_net_timestep;
123      }
124      if (new_solver_timestep < m_params.m_min_timestep)
125         new_solver_timestep = m_params.m_min_timestep;
126   }
127   //if (new_solver_timestep > 10.0 * hn)
128   //    new_solver_timestep = 10.0 * hn;
129   return new_solver_timestep;
130}
131
132template <unsigned m_N, unsigned _storage_N>
133ATTR_COLD void matrix_solver_direct_t<m_N, _storage_N>::add_term(int k, terminal_t *term)
134{
135   if (term->m_otherterm->net().isRailNet())
136   {
137      m_rails_temp[k].add(term, -1, false);
138   }
139   else
140   {
141      int ot = get_net_idx(&term->m_otherterm->net());
142      if (ot>=0)
143      {
144         m_terms[k]->add(term, ot, true);
145      }
146      /* Should this be allowed ? */
147      else // if (ot<0)
148      {
149         m_rails_temp[k].add(term, ot, true);
150         log().fatal("found term with missing othernet {1}\n", term->name());
151      }
152   }
153}
154
155
156template <unsigned m_N, unsigned _storage_N>
157ATTR_COLD void matrix_solver_direct_t<m_N, _storage_N>::vsetup(analog_net_t::list_t &nets)
158{
159   if (m_dim < nets.size())
160      log().fatal("Dimension {1} less than {2}", m_dim, nets.size());
161
162   for (unsigned k = 0; k < N(); k++)
163   {
164      m_terms[k]->clear();
165      m_rails_temp[k].clear();
166   }
167
168   matrix_solver_t::setup(nets);
169
170   for (unsigned k = 0; k < N(); k++)
171   {
172      m_terms[k]->m_railstart = m_terms[k]->count();
173      for (unsigned i = 0; i < m_rails_temp[k].count(); i++)
174         this->m_terms[k]->add(m_rails_temp[k].terms()[i], m_rails_temp[k].net_other()[i], false);
175
176      m_rails_temp[k].clear(); // no longer needed
177      m_terms[k]->set_pointers();
178   }
179
180#if 1
181
182   /* Sort in descending order by number of connected matrix voltages.
183    * The idea is, that for Gauss-Seidel algo the first voltage computed
184    * depends on the greatest number of previous voltages thus taking into
185    * account the maximum amout of information.
186    *
187    * This actually improves performance on popeye slightly. Average
188    * GS computations reduce from 2.509 to 2.370
189    *
190    * Smallest to largest : 2.613
191    * Unsorted            : 2.509
192    * Largest to smallest : 2.370
193    *
194    * Sorting as a general matrix pre-conditioning is mentioned in
195    * literature but I have found no articles about Gauss Seidel.
196    *
197    * For Gaussian Elimination however increasing order is better suited.
198    * FIXME: Even better would be to sort on elements right of the matrix diagonal.
199    *
200    */
201
202   int sort_order = (type() == GAUSS_SEIDEL ? 1 : -1);
203
204   for (unsigned k = 0; k < N() / 2; k++)
205      for (unsigned i = 0; i < N() - 1; i++)
206      {
207         if ((m_terms[i]->m_railstart - m_terms[i+1]->m_railstart) * sort_order < 0)
208         {
209            std::swap(m_terms[i],m_terms[i+1]);
210            m_nets.swap(i, i+1);
211         }
212      }
213
214   for (unsigned k = 0; k < N(); k++)
215   {
216      int *other = m_terms[k]->net_other();
217      for (unsigned i = 0; i < m_terms[k]->count(); i++)
218         if (other[i] != -1)
219            other[i] = get_net_idx(&m_terms[k]->terms()[i]->m_otherterm->net());
220   }
221
222#endif
223
224   /* create a list of non zero elements right of the diagonal
225    * These list anticipate the population of array elements by
226    * Gaussian elimination.
227    */
228   for (unsigned k = 0; k < N(); k++)
229   {
230      terms_t * t = m_terms[k];
231      /* pretty brutal */
232      int *other = t->net_other();
233
234      t->m_nz.clear();
235
236      if (k==0)
237         t->m_nzrd.clear();
238      else
239      {
240         t->m_nzrd = m_terms[k-1]->m_nzrd;
241         unsigned j=0;
242         while(j < t->m_nzrd.size())
243         {
244            if (t->m_nzrd[j] < k + 1)
245               t->m_nzrd.remove_at(j);
246            else
247               j++;
248         }
249      }
250
251      for (unsigned j = 0; j < N(); j++)
252      {
253         for (unsigned i = 0; i < t->m_railstart; i++)
254         {
255            if (!t->m_nzrd.contains(other[i]) && other[i] >= (int) (k + 1))
256               t->m_nzrd.add(other[i]);
257            if (!t->m_nz.contains(other[i]))
258               t->m_nz.add(other[i]);
259         }
260      }
261      psort_list(t->m_nzrd);
262
263      t->m_nz.add(k);     // add diagonal
264      psort_list(t->m_nz);
265   }
266
267   /* create a list of non zero elements below diagonal k
268    * This should reduce cache misses ...
269    */
270
271   bool touched[_storage_N][_storage_N] = { { false } };
272   for (unsigned k = 0; k < N(); k++)
273   {
274      m_terms[k]->m_nzbd.clear();
275      for (unsigned j = 0; j < m_terms[k]->m_nz.size(); j++)
276         touched[k][m_terms[k]->m_nz[j]] = true;
277   }
278
279   for (unsigned k = 0; k < N(); k++)
280   {
281      for (unsigned row = k + 1; row < N(); row++)
282      {
283         if (touched[row][k])
284         {
285            if (!m_terms[k]->m_nzbd.contains(row))
286               m_terms[k]->m_nzbd.add(row);
287            for (unsigned col = k; col < N(); col++)
288               if (touched[k][col])
289                  touched[row][col] = true;
290         }
291      }
292   }
293
294   if (0)
295      for (unsigned k = 0; k < N(); k++)
296      {
297         pstring line = pfmt("{1}")(k, "3");
298         for (unsigned j = 0; j < m_terms[k]->m_nzrd.size(); j++)
299            line += pfmt(" {1}")(m_terms[k]->m_nzrd[j], "3");
300         log().verbose("{1}", line);
301      }
302
303   /*
304    * save states
305    */
306   save(NLNAME(m_RHS));
307   save(NLNAME(m_last_RHS));
308   save(NLNAME(m_last_V));
309
310   for (unsigned k = 0; k < N(); k++)
311   {
312      pstring num = pfmt("{1}")(k);
313
314      save(m_terms[k]->go(),"GO" + num, m_terms[k]->count());
315      save(m_terms[k]->gt(),"GT" + num, m_terms[k]->count());
316      save(m_terms[k]->Idr(),"IDR" + num , m_terms[k]->count());
317   }
318
319}
320
321
322template <unsigned m_N, unsigned _storage_N>
323ATTR_HOT void matrix_solver_direct_t<m_N, _storage_N>::build_LE_A()
324{
325   const unsigned iN = N();
326   for (unsigned k = 0; k < iN; k++)
327   {
328      for (unsigned i=0; i < iN; i++)
329         A(k,i) = 0.0;
330
331      const unsigned terms_count = m_terms[k]->count();
332      const unsigned railstart =  m_terms[k]->m_railstart;
333      const nl_double * RESTRICT gt = m_terms[k]->gt();
334
335      {
336         nl_double akk  = 0.0;
337         for (unsigned i = 0; i < terms_count; i++)
338            akk += gt[i];
339
340         A(k,k) = akk;
341      }
342
343      const nl_double * RESTRICT go = m_terms[k]->go();
344      const int * RESTRICT net_other = m_terms[k]->net_other();
345
346      for (unsigned i = 0; i < railstart; i++)
347         A(k,net_other[i]) -= go[i];
348   }
349}
350
351template <unsigned m_N, unsigned _storage_N>
352ATTR_HOT void matrix_solver_direct_t<m_N, _storage_N>::build_LE_RHS(nl_double * RESTRICT rhs)
353{
354   const unsigned iN = N();
355   for (unsigned k = 0; k < iN; k++)
356   {
357      nl_double rhsk_a = 0.0;
358      nl_double rhsk_b = 0.0;
359
360      const int terms_count = m_terms[k]->count();
361      const nl_double * RESTRICT go = m_terms[k]->go();
362      const nl_double * RESTRICT Idr = m_terms[k]->Idr();
363      const nl_double * const * RESTRICT other_cur_analog = m_terms[k]->other_curanalog();
364
365      for (int i = 0; i < terms_count; i++)
366         rhsk_a = rhsk_a + Idr[i];
367
368      for (int i = m_terms[k]->m_railstart; i < terms_count; i++)
369         //rhsk = rhsk + go[i] * terms[i]->m_otherterm->net().as_analog().Q_Analog();
370         rhsk_b = rhsk_b + go[i] * *other_cur_analog[i];
371
372      rhs[k] = rhsk_a + rhsk_b;
373   }
374}
375
376template <unsigned m_N, unsigned _storage_N>
377ATTR_HOT void matrix_solver_direct_t<m_N, _storage_N>::LE_solve()
378{
379   const unsigned kN = N();
380
381   for (unsigned i = 0; i < kN; i++) {
382      // FIXME: use a parameter to enable pivoting? m_pivot
383      if (m_params.m_pivot)
384      {
385         /* Find the row with the largest first value */
386         unsigned maxrow = i;
387         for (unsigned j = i + 1; j < kN; j++)
388         {
389            //if (std::abs(m_A[j][i]) > std::abs(m_A[maxrow][i]))
390            if (A(j,i) * A(j,i) > A(maxrow,i) * A(maxrow,i))
391               maxrow = j;
392         }
393
394         if (maxrow != i)
395         {
396            /* Swap the maxrow and ith row */
397            for (unsigned k = 0; k < kN; k++) {
398               std::swap(A(i,k), A(maxrow,k));
399            }
400            std::swap(m_RHS[i], m_RHS[maxrow]);
401         }
402         /* FIXME: Singular matrix? */
403         const nl_double f = 1.0 / A(i,i);
404
405         /* Eliminate column i from row j */
406
407         for (unsigned j = i + 1; j < kN; j++)
408         {
409            const nl_double f1 = - A(j,i) * f;
410            if (f1 != NL_FCONST(0.0))
411            {
412               for (unsigned k = i+1; k < kN; k++)
413                  A(j,k) += A(i,k) * f1;
414               m_RHS[j] += m_RHS[i] * f1;
415            }
416         }
417      }
418      else
419      {
420         /* FIXME: Singular matrix? */
421         const nl_double f = 1.0 / A(i,i);
422         const unsigned * RESTRICT const p = m_terms[i]->m_nzrd.data();
423         const unsigned e = m_terms[i]->m_nzrd.size();
424
425         /* Eliminate column i from row j */
426
427         const unsigned * RESTRICT const pb = m_terms[i]->m_nzbd.data();
428         const unsigned eb = m_terms[i]->m_nzbd.size();
429         for (unsigned jb = 0; jb < eb; jb++)
430         {
431            const unsigned j = pb[jb];
432            const nl_double f1 = - A(j,i) * f;
433            for (unsigned k = 0; k < e; k++)
434            {
435               A(j,p[k]) += A(i,p[k]) * f1;
436            }
437            m_RHS[j] += m_RHS[i] * f1;
438         }
439      }
440   }
441}
442
443template <unsigned m_N, unsigned _storage_N>
444ATTR_HOT void matrix_solver_direct_t<m_N, _storage_N>::LE_back_subst(
445      nl_double * RESTRICT x)
446{
447   const unsigned kN = N();
448
449   /* back substitution */
450   if (m_params.m_pivot)
451   {
452      for (int j = kN - 1; j >= 0; j--)
453      {
454         nl_double tmp = 0;
455         for (unsigned k = j+1; k < kN; k++)
456            tmp += A(j,k) * x[k];
457         x[j] = (m_RHS[j] - tmp) / A(j,j);
458      }
459   }
460   else
461   {
462      for (int j = kN - 1; j >= 0; j--)
463      {
464         nl_double tmp = 0;
465
466         const unsigned *p = m_terms[j]->m_nzrd.data();
467         const unsigned e = m_terms[j]->m_nzrd.size();
468
469         for (unsigned k = 0; k < e; k++)
470         {
471            const unsigned pk = p[k];
472            tmp += A(j,pk) * x[pk];
473         }
474         x[j] = (m_RHS[j] - tmp) / A(j,j);
475      }
476   }
477}
478
479template <unsigned m_N, unsigned _storage_N>
480ATTR_HOT void matrix_solver_direct_t<m_N, _storage_N>::LE_back_subst_full(
481      nl_double * RESTRICT x)
482{
483   const unsigned kN = N();
484
485   /* back substitution */
486
487   // int ip;
488   // ii=-1
489
490   //for (int i=0; i < kN; i++)
491   //  x[i] = m_RHS[i];
492
493   for (int i=0; i < kN; i++)
494   {
495      //ip=indx[i]; USE_PIVOT_SEARCH
496      //sum=b[ip];
497      //b[ip]=b[i];
498      double sum=m_RHS[i];//x[i];
499      for (int j=0; j < i; j++)
500         sum -= A(i,j) * x[j];
501      x[i]=sum;
502   }
503   for (int i=kN-1; i >= 0; i--)
504   {
505      double sum=x[i];
506      for (int j = i+1; j < kN; j++)
507         sum -= A(i,j)*x[j];
508      x[i] = sum / A(i,i);
509   }
510
511}
512
513template <unsigned m_N, unsigned _storage_N>
514ATTR_HOT nl_double matrix_solver_direct_t<m_N, _storage_N>::delta(
515      const nl_double * RESTRICT V)
516{
517   /* FIXME: Ideally we should also include currents (RHS) here. This would
518    * need a revaluation of the right hand side after voltages have been updated
519    * and thus belong into a different calculation. This applies to all solvers.
520    */
521
522   const unsigned iN = this->N();
523   nl_double cerr = 0;
524   for (unsigned i = 0; i < iN; i++)
525      cerr = std::max(cerr, nl_math::abs(V[i] - this->m_nets[i]->m_cur_Analog));
526   return cerr;
527}
528
529template <unsigned m_N, unsigned _storage_N>
530ATTR_HOT void matrix_solver_direct_t<m_N, _storage_N>::store(
531      const nl_double * RESTRICT V)
532{
533   for (unsigned i = 0, iN=N(); i < iN; i++)
534   {
535      this->m_nets[i]->m_cur_Analog = V[i];
536   }
537}
538
539template <unsigned m_N, unsigned _storage_N>
540ATTR_HOT nl_double matrix_solver_direct_t<m_N, _storage_N>::vsolve()
541{
542   this->solve_base(this);
543   return this->compute_next_timestep();
544}
545
546
547template <unsigned m_N, unsigned _storage_N>
548ATTR_HOT int matrix_solver_direct_t<m_N, _storage_N>::solve_non_dynamic(ATTR_UNUSED const bool newton_raphson)
549{
550   nl_double new_V[_storage_N]; // = { 0.0 };
551
552   this->LE_back_subst(new_V);
553
554   if (newton_raphson)
555   {
556      nl_double err = delta(new_V);
557
558      store(new_V);
559
560      return (err > this->m_params.m_accuracy) ? 2 : 1;
561   }
562   else
563   {
564      store(new_V);
565      return 1;
566   }
567}
568
569template <unsigned m_N, unsigned _storage_N>
570ATTR_HOT inline int matrix_solver_direct_t<m_N, _storage_N>::vsolve_non_dynamic(const bool newton_raphson)
571{
572   this->build_LE_A();
573   this->build_LE_RHS(m_last_RHS);
574
575   for (unsigned i=0, iN=N(); i < iN; i++)
576      m_RHS[i] = m_last_RHS[i];
577
578   this->LE_solve();
579
580   return this->solve_non_dynamic(newton_raphson);
581}
582
583template <unsigned m_N, unsigned _storage_N>
584matrix_solver_direct_t<m_N, _storage_N>::matrix_solver_direct_t(const solver_parameters_t *params, const int size)
585: matrix_solver_t(GAUSSIAN_ELIMINATION, params)
586, m_dim(size)
587{
588   m_terms = palloc_array(terms_t *, N());
589   m_rails_temp = palloc_array(terms_t, N());
590
591   for (unsigned k = 0; k < N(); k++)
592   {
593      m_terms[k] = palloc(terms_t);
594      m_last_RHS[k] = 0.0;
595      m_last_V[k] = 0.0;
596   }
597}
598
599template <unsigned m_N, unsigned _storage_N>
600matrix_solver_direct_t<m_N, _storage_N>::matrix_solver_direct_t(const eSolverType type, const solver_parameters_t *params, const int size)
601: matrix_solver_t(type, params)
602, m_dim(size)
603{
604   m_terms = palloc_array(terms_t *, N());
605   m_rails_temp = palloc_array(terms_t, N());
606
607   for (unsigned k = 0; k < N(); k++)
608   {
609      m_terms[k] = palloc(terms_t);
610      m_last_RHS[k] = 0.0;
611      m_last_V[k] = 0.0;
612   }
613}
614
615NETLIB_NAMESPACE_DEVICES_END()
616
617#endif /* NLD_MS_DIRECT_H_ */
trunk/src/lib/netlist/solver/nld_ms_direct1.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_ms_direct1.h
5 *
6 */
7
8#ifndef NLD_MS_DIRECT1_H_
9#define NLD_MS_DIRECT1_H_
10
11#include "solver/nld_ms_direct.h"
12#include "solver/nld_solver.h"
13
14NETLIB_NAMESPACE_DEVICES_START()
15
16class matrix_solver_direct1_t: public matrix_solver_direct_t<1,1>
17{
18public:
19
20   matrix_solver_direct1_t(const solver_parameters_t *params)
21      : matrix_solver_direct_t<1, 1>(params, 1)
22      {}
23   ATTR_HOT inline int vsolve_non_dynamic(const bool newton_raphson);
24protected:
25   ATTR_HOT virtual nl_double vsolve();
26private:
27};
28
29// ----------------------------------------------------------------------------------------
30// matrix_solver - Direct1
31// ----------------------------------------------------------------------------------------
32
33ATTR_HOT nl_double matrix_solver_direct1_t::vsolve()
34{
35   solve_base<matrix_solver_direct1_t>(this);
36   return this->compute_next_timestep();
37}
38
39ATTR_HOT inline int matrix_solver_direct1_t::vsolve_non_dynamic(ATTR_UNUSED const bool newton_raphson)
40{
41   analog_net_t *net = m_nets[0];
42   this->build_LE_A();
43   this->build_LE_RHS(m_RHS);
44   //NL_VERBOSE_OUT(("{1} {2}\n", new_val, m_RHS[0] / m_A[0][0]);
45
46   nl_double new_val =  m_RHS[0] / A(0,0);
47
48   nl_double e = (new_val - net->m_cur_Analog);
49   nl_double cerr = nl_math::abs(e);
50
51   net->m_cur_Analog = new_val;
52
53   if (is_dynamic() && (cerr  > m_params.m_accuracy))
54   {
55      return 2;
56   }
57   else
58      return 1;
59
60}
61
62NETLIB_NAMESPACE_DEVICES_END()
63
64
65#endif /* NLD_MS_DIRECT1_H_ */
trunk/src/lib/netlist/solver/nld_ms_direct2.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_ms_direct1.h
5 *
6 */
7
8#ifndef NLD_MS_DIRECT2_H_
9#define NLD_MS_DIRECT2_H_
10
11#include "solver/nld_ms_direct.h"
12#include "solver/nld_solver.h"
13
14NETLIB_NAMESPACE_DEVICES_START()
15
16class matrix_solver_direct2_t: public matrix_solver_direct_t<2,2>
17{
18public:
19
20   matrix_solver_direct2_t(const solver_parameters_t *params)
21      : matrix_solver_direct_t<2, 2>(params, 2)
22      {}
23   ATTR_HOT inline int vsolve_non_dynamic(const bool newton_raphson);
24protected:
25   ATTR_HOT virtual nl_double vsolve();
26private:
27};
28
29// ----------------------------------------------------------------------------------------
30// matrix_solver - Direct2
31// ----------------------------------------------------------------------------------------
32
33ATTR_HOT nl_double matrix_solver_direct2_t::vsolve()
34{
35   solve_base<matrix_solver_direct2_t>(this);
36   return this->compute_next_timestep();
37}
38
39ATTR_HOT inline int matrix_solver_direct2_t::vsolve_non_dynamic(ATTR_UNUSED const bool newton_raphson)
40{
41   build_LE_A();
42   build_LE_RHS(m_RHS);
43
44   const nl_double a = A(0,0);
45   const nl_double b = A(0,1);
46   const nl_double c = A(1,0);
47   const nl_double d = A(1,1);
48
49   nl_double new_val[2];
50   new_val[1] = (a * m_RHS[1] - c * m_RHS[0]) / (a * d - b * c);
51   new_val[0] = (m_RHS[0] - b * new_val[1]) / a;
52
53   if (is_dynamic())
54   {
55      nl_double err = this->delta(new_val);
56      store(new_val);
57      if (err > m_params.m_accuracy )
58         return 2;
59      else
60         return 1;
61   }
62   store(new_val);
63   return 1;
64}
65
66NETLIB_NAMESPACE_DEVICES_END()
67
68#endif /* NLD_MS_DIRECT2_H_ */
trunk/src/lib/netlist/solver/nld_ms_direct_lu.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_ms_direct.h
5 *
6 */
7
8#ifndef NLD_MS_DIRECT_H_
9#define NLD_MS_DIRECT_H_
10
11#include <algorithm>
12
13#include "solver/nld_solver.h"
14
15//#define A(_r, _c) m_A[_r][_c]
16
17NETLIB_NAMESPACE_DEVICES_START()
18
19//#define nl_ext_double __float128 // slow, very slow
20//#define nl_ext_double long double // slightly slower
21#define nl_ext_double double
22
23template <unsigned m_N, unsigned _storage_N>
24class matrix_solver_direct_t: public matrix_solver_t
25{
26public:
27
28   matrix_solver_direct_t(const solver_parameters_t *params, const int size);
29   matrix_solver_direct_t(const eSolverType type, const solver_parameters_t *params, const int size);
30
31   virtual ~matrix_solver_direct_t();
32
33   virtual void vsetup(analog_net_t::list_t &nets);
34   virtual void reset() { matrix_solver_t::reset(); }
35
36   ATTR_HOT inline unsigned N() const { if (m_N == 0) return m_dim; else return m_N; }
37
38   ATTR_HOT inline int vsolve_non_dynamic(const bool newton_raphson);
39
40protected:
41   virtual void add_term(int net_idx, terminal_t *term);
42
43   ATTR_HOT virtual nl_double vsolve();
44
45   ATTR_HOT int solve_non_dynamic(const bool newton_raphson);
46   ATTR_HOT void build_LE_A();
47   ATTR_HOT void build_LE_RHS(nl_double * RESTRICT rhs);
48
49   template<unsigned k>
50   void LEk()
51   {
52      //const unsigned kN = N();
53
54      const double akki = 1.0 / A(k,k);
55      const unsigned * const p = m_terms[k]->m_nzrd.data();
56      const unsigned e = m_terms[k]->m_nzrd.size();
57
58      for (int i = k+1; i < _storage_N;i++)
59      {
60         const double alpha = A(i,k) * akki;
61         A(i,k) = alpha;
62         if (alpha != 0.0)
63            for (int j = 0; j < e; j++)
64            {
65               const int pk = p[j];
66               A(i,pk) -= A(k,pk) * alpha;
67            }
68      }
69   }
70
71   ATTR_HOT void LE_solve()
72   {
73      const unsigned kN = N();
74      unsigned sk = 1;
75
76      if (1 && kN == _storage_N)
77      {
78         if (kN> 0 ) LEk<0>();
79         if (kN> 1 ) LEk<1>();
80         if (kN> 2 ) LEk<2>();
81         if (kN> 3 ) LEk<3>();
82         if (kN> 4 ) LEk<4>();
83         if (kN> 5 ) LEk<5>();
84         if (kN> 6 ) LEk<6>();
85         if (kN> 7 ) LEk<7>();
86         if (kN> 8 ) LEk<8>();
87         if (kN> 9 ) LEk<9>();
88         if (kN>10 ) LEk<10>();
89         if (kN>11 ) LEk<11>();
90         if (kN>12 ) LEk<12>();
91         if (kN>13 ) LEk<13>();
92         if (kN>14 ) LEk<14>();
93         if (kN>15 ) LEk<15>();
94         if (kN>16 ) LEk<16>();
95         if (kN>17 ) LEk<17>();
96         if (kN>18 ) LEk<18>();
97         if (kN>19 ) LEk<19>();
98         if (kN>20 ) LEk<20>();
99         if (kN>21 ) LEk<21>();
100         if (kN>22 ) LEk<22>();
101         if (kN>23 ) LEk<23>();
102         if (kN>24 ) LEk<24>();
103         if (kN>25 ) LEk<25>();
104         if (kN>26 ) LEk<26>();
105         if (kN>27 ) LEk<27>();
106         if (kN>28 ) LEk<28>();
107         if (kN>29 ) LEk<29>();
108         sk = 30;
109      }
110
111      for (int k = sk; k < kN - 1; k++)
112      {
113         const double akki = 1.0 / A(k,k);
114         const unsigned * const p = m_terms[k]->m_nzrd.data();
115         const unsigned e = m_terms[k]->m_nzrd.size();
116
117         for (int i = k+1; i < kN;i++)
118         {
119            const double alpha = A(i,k) * akki;
120            A(i,k) = alpha;
121            if (alpha != 0.0)
122               for (int j = 0; j < e; j++)
123               {
124                  const int pk = p[j];
125                  A(i,pk) -= A(k,pk) * alpha;
126               }
127         }
128      }
129   }
130   ATTR_HOT void LE_back_subst(nl_double * RESTRICT x);
131   ATTR_HOT nl_double delta(const nl_double * RESTRICT V);
132   ATTR_HOT void store(const nl_double * RESTRICT V);
133
134   /* bring the whole system to the current time
135    * Don't schedule a new calculation time. The recalculation has to be
136    * triggered by the caller after the netlist element was changed.
137    */
138   ATTR_HOT nl_double compute_next_timestep();
139
140   template <typename T1, typename T2>
141   inline nl_ext_double &A(const T1 r, const T2 c) { return m_A[r][c]; }
142
143   //ATTR_ALIGN nl_double m_A[_storage_N][((_storage_N + 7) / 8) * 8];
144   ATTR_ALIGN nl_double m_RHS[_storage_N];
145   ATTR_ALIGN nl_double m_last_RHS[_storage_N]; // right hand side - contains currents
146   ATTR_ALIGN nl_double m_last_V[_storage_N];
147
148   terms_t **m_terms;
149   terms_t *m_rails_temp;
150
151private:
152   ATTR_ALIGN nl_ext_double m_A[_storage_N][((_storage_N + 7) / 8) * 8];
153
154   const unsigned m_dim;
155   nl_double m_lp_fact;
156};
157
158// ----------------------------------------------------------------------------------------
159// matrix_solver_direct
160// ----------------------------------------------------------------------------------------
161
162template <unsigned m_N, unsigned _storage_N>
163matrix_solver_direct_t<m_N, _storage_N>::~matrix_solver_direct_t()
164{
165   for (unsigned k = 0; k < N(); k++)
166   {
167      pfree(m_terms[k]);
168   }
169   pfree_array(m_terms);
170   pfree_array(m_rails_temp);
171}
172
173template <unsigned m_N, unsigned _storage_N>
174ATTR_HOT nl_double matrix_solver_direct_t<m_N, _storage_N>::compute_next_timestep()
175{
176   nl_double new_solver_timestep = m_params.m_max_timestep;
177
178   if (m_params.m_dynamic)
179   {
180      /*
181       * FIXME: We should extend the logic to use either all nets or
182       *        only output nets.
183       */
184      for (unsigned k = 0, iN=N(); k < iN; k++)
185      {
186         analog_net_t *n = m_nets[k];
187
188         const nl_double DD_n = (n->m_cur_Analog - m_last_V[k]);
189         const nl_double hn = current_timestep();
190
191         nl_double DD2 = (DD_n / hn - n->m_DD_n_m_1 / n->m_h_n_m_1) / (hn + n->m_h_n_m_1);
192         nl_double new_net_timestep;
193
194         n->m_h_n_m_1 = hn;
195         n->m_DD_n_m_1 = DD_n;
196         if (nl_math::abs(DD2) > NL_FCONST(1e-30)) // avoid div-by-zero
197            new_net_timestep = nl_math::sqrt(m_params.m_lte / nl_math::abs(NL_FCONST(0.5)*DD2));
198         else
199            new_net_timestep = m_params.m_max_timestep;
200
201         if (new_net_timestep < new_solver_timestep)
202            new_solver_timestep = new_net_timestep;
203      }
204      if (new_solver_timestep < m_params.m_min_timestep)
205         new_solver_timestep = m_params.m_min_timestep;
206   }
207   //if (new_solver_timestep > 10.0 * hn)
208   //    new_solver_timestep = 10.0 * hn;
209   return new_solver_timestep;
210}
211
212template <unsigned m_N, unsigned _storage_N>
213ATTR_COLD void matrix_solver_direct_t<m_N, _storage_N>::add_term(int k, terminal_t *term)
214{
215   if (term->m_otherterm->net().isRailNet())
216   {
217      m_rails_temp[k].add(term, -1, false);
218   }
219   else
220   {
221      int ot = get_net_idx(&term->m_otherterm->net());
222      if (ot>=0)
223      {
224         m_terms[k]->add(term, ot, true);
225      }
226      /* Should this be allowed ? */
227      else // if (ot<0)
228      {
229         m_rails_temp[k].add(term, ot, true);
230         netlist().error("found term with missing othernet {1}\n", term->name());
231      }
232   }
233}
234
235
236template <unsigned m_N, unsigned _storage_N>
237ATTR_COLD void matrix_solver_direct_t<m_N, _storage_N>::vsetup(analog_net_t::list_t &nets)
238{
239   if (m_dim < nets.size())
240      netlist().error("Dimension {1} less than {2}", m_dim, SIZET_PRINTF(nets.size()));
241
242   for (unsigned k = 0; k < N(); k++)
243   {
244      m_terms[k]->clear();
245      m_rails_temp[k].clear();
246   }
247
248   matrix_solver_t::setup(nets);
249
250   for (unsigned k = 0; k < N(); k++)
251   {
252      m_terms[k]->m_railstart = m_terms[k]->count();
253      for (unsigned i = 0; i < m_rails_temp[k].count(); i++)
254         this->m_terms[k]->add(m_rails_temp[k].terms()[i], m_rails_temp[k].net_other()[i], false);
255
256      m_rails_temp[k].clear(); // no longer needed
257      m_terms[k]->set_pointers();
258   }
259
260#if 1
261
262   /* Sort in descending order by number of connected matrix voltages.
263    * The idea is, that for Gauss-Seidel algo the first voltage computed
264    * depends on the greatest number of previous voltages thus taking into
265    * account the maximum amout of information.
266    *
267    * This actually improves performance on popeye slightly. Average
268    * GS computations reduce from 2.509 to 2.370
269    *
270    * Smallest to largest : 2.613
271    * Unsorted            : 2.509
272    * Largest to smallest : 2.370
273    *
274    * Sorting as a general matrix pre-conditioning is mentioned in
275    * literature but I have found no articles about Gauss Seidel.
276    *
277    * For Gaussian Elimination however increasing order is better suited.
278    * FIXME: Even better would be to sort on elements right of the matrix diagonal.
279    *
280    */
281
282   int sort_order = (type() == GAUSS_SEIDEL ? 1 : -1);
283
284   for (unsigned k = 0; k < N() / 2; k++)
285      for (unsigned i = 0; i < N() - 1; i++)
286      {
287         if ((m_terms[i]->m_railstart - m_terms[i+1]->m_railstart) * sort_order < 0)
288         {
289            std::swap(m_terms[i],m_terms[i+1]);
290            m_nets.swap(i, i+1);
291         }
292      }
293
294   for (unsigned k = 0; k < N(); k++)
295   {
296      int *other = m_terms[k]->net_other();
297      for (unsigned i = 0; i < m_terms[k]->count(); i++)
298         if (other[i] != -1)
299            other[i] = get_net_idx(&m_terms[k]->terms()[i]->m_otherterm->net());
300   }
301
302#endif
303
304   /* create a list of non zero elements right of the diagonal
305    * These list anticipate the population of array elements by
306    * Gaussian elimination.
307    */
308   for (unsigned k = 0; k < N(); k++)
309   {
310      terms_t * t = m_terms[k];
311      /* pretty brutal */
312      int *other = t->net_other();
313
314      t->m_nz.clear();
315
316      if (k==0)
317         t->m_nzrd.clear();
318      else
319      {
320         t->m_nzrd = m_terms[k-1]->m_nzrd;
321         unsigned j=0;
322         while(j < t->m_nzrd.size())
323         {
324            if (t->m_nzrd[j] < k + 1)
325               t->m_nzrd.remove_at(j);
326            else
327               j++;
328         }
329      }
330
331      for (unsigned j = 0; j < N(); j++)
332      {
333         for (unsigned i = 0; i < t->m_railstart; i++)
334         {
335            if (!t->m_nzrd.contains(other[i]) && other[i] >= (int) (k + 1))
336               t->m_nzrd.add(other[i]);
337            if (!t->m_nz.contains(other[i]))
338               t->m_nz.add(other[i]);
339         }
340      }
341      psort_list(t->m_nzrd);
342
343      t->m_nz.add(k);     // add diagonal
344      psort_list(t->m_nz);
345   }
346
347   if(0)
348      for (unsigned k = 0; k < N(); k++)
349      {
350         netlist().log("{1:3}: ", k);
351         for (unsigned j = 0; j < m_terms[k]->m_nzrd.size(); j++)
352            netlist().log(" {1:3}", m_terms[k]->m_nzrd[j]);
353         netlist().log("\n");
354      }
355
356   /*
357    * save states
358    */
359   save(NLNAME(m_RHS));
360   save(NLNAME(m_last_RHS));
361   save(NLNAME(m_last_V));
362
363   for (unsigned k = 0; k < N(); k++)
364   {
365      pstring num = pfmt("{1}")(k);
366
367      save(m_terms[k]->go(),"GO" + num, m_terms[k]->count());
368      save(m_terms[k]->gt(),"GT" + num, m_terms[k]->count());
369      save(m_terms[k]->Idr(),"IDR" + num , m_terms[k]->count());
370   }
371
372}
373
374
375template <unsigned m_N, unsigned _storage_N>
376ATTR_HOT void matrix_solver_direct_t<m_N, _storage_N>::build_LE_A()
377{
378   const unsigned iN = N();
379   for (unsigned k = 0; k < iN; k++)
380   {
381      for (unsigned i=0; i < iN; i++)
382         A(k,i) = 0.0;
383
384      nl_double akk  = 0.0;
385      const unsigned terms_count = m_terms[k]->count();
386      const unsigned railstart =  m_terms[k]->m_railstart;
387      const nl_double * RESTRICT gt = m_terms[k]->gt();
388      const nl_double * RESTRICT go = m_terms[k]->go();
389      const int * RESTRICT net_other = m_terms[k]->net_other();
390
391      for (unsigned i = 0; i < terms_count; i++)
392         akk = akk + gt[i];
393
394      A(k,k) += akk;
395
396      for (unsigned i = 0; i < railstart; i++)
397         A(k, net_other[i]) -= go[i];
398   }
399}
400
401template <unsigned m_N, unsigned _storage_N>
402ATTR_HOT void matrix_solver_direct_t<m_N, _storage_N>::build_LE_RHS(nl_double * RESTRICT rhs)
403{
404   const unsigned iN = N();
405   for (unsigned k = 0; k < iN; k++)
406   {
407      nl_double rhsk_a = 0.0;
408      nl_double rhsk_b = 0.0;
409
410      const int terms_count = m_terms[k]->count();
411      const nl_double * RESTRICT go = m_terms[k]->go();
412      const nl_double * RESTRICT Idr = m_terms[k]->Idr();
413      const nl_double * const * RESTRICT other_cur_analog = m_terms[k]->other_curanalog();
414
415      for (int i = 0; i < terms_count; i++)
416         rhsk_a = rhsk_a + Idr[i];
417
418      for (int i = m_terms[k]->m_railstart; i < terms_count; i++)
419         //rhsk = rhsk + go[i] * terms[i]->m_otherterm->net().as_analog().Q_Analog();
420         rhsk_b = rhsk_b + go[i] * *other_cur_analog[i];
421
422      rhs[k] = rhsk_a + rhsk_b;
423   }
424}
425
426#if 1
427#else
428// Crout algo
429template <unsigned m_N, unsigned _storage_N>
430ATTR_HOT void matrix_solver_direct_t<m_N, _storage_N>::LE_solve()
431{
432   const unsigned kN = N();
433
434   ATTR_UNUSED int imax;
435   ATTR_UNUSED double big,temp;
436
437#if 0
438   double vv[_storage_N];
439
440   for (i=0;i<kN;i++)
441   {
442      big=0.0;
443      for (j=0;j<kN;j++)
444         if ((temp=fabs(m_A[i][j])) > big)
445            big=temp;
446      //if (big == 0.0) nrerror("Singular matrix in routine LUDCMP");
447      vv[i]=1.0/big;
448   }
449#endif
450   for (int j = 0; j < kN; j++)
451   {
452#if 1
453      for (int i=0; i < kN;i++)
454      {
455         double sum = 0.0;
456         const int e = (i<j ? i : j);
457         for (int k=0; k < e; k++)
458            sum += A(i,k) * A(k,j);
459         A(i,j) -= sum;
460      }
461#else
462      for (int i=0; i < j;i++)
463      {
464         double * RESTRICT p = m_A[i];
465         double sum = 0.0;
466         for (int k=0; k < i; k++)
467            sum += p[k] * m_A[k][j];
468         p[j] -= sum;
469      }
470      big=0.0;
471      for (int i = j; i < kN; i++)
472      {
473         double * RESTRICT p = m_A[i];
474         double sum = 0.0;
475         for (int k = 0; k < j; k++)
476            sum += p[k] * m_A[k][j];
477         p[j] -= sum;
478#if 0
479         if ( (dum=vv[i]*fabs(sum)) >= big) {
480            big=dum;
481            imax=i;
482         }
483#endif
484      }
485#endif
486#if 0
487      // USE_PIVOT_SEARCH
488      // omit pivoting for now
489      if (j != imax)
490      {
491         for (k=0;k<kN;k++)
492         {
493            dum=m_A[imax][k];
494            m_A[imax][k]=m_A[j][k];
495            m_A[j][k]=dum;
496         }
497         //*d = -(*d);
498         vv[imax]=vv[j];
499      }
500      indx[j]=imax;
501#endif
502      //if (m_A[j][j] == 0.0)
503      //  m_A[j][j] = 1e-20;
504      double dum = 1.0 / A(j,j);
505      for (int i = j+1; i < kN; i++)
506         A(i,j) *= dum;
507   }
508}
509#endif
510
511template <unsigned m_N, unsigned _storage_N>
512ATTR_HOT void matrix_solver_direct_t<m_N, _storage_N>::LE_back_subst(
513      nl_double * RESTRICT x)
514{
515   const unsigned kN = N();
516
517   /* back substitution */
518
519   // int ip;
520   // ii=-1
521
522   //for (int i=0; i < kN; i++)
523   //  x[i] = m_RHS[i];
524
525   for (int i=0; i < kN; i++)
526   {
527      //ip=indx[i]; USE_PIVOT_SEARCH
528      //sum=b[ip];
529      //b[ip]=b[i];
530      double sum=m_RHS[i];//x[i];
531      for (int j=0; j < i; j++)
532         sum -= A(i,j) * x[j];
533      x[i]=sum;
534   }
535   for (int i=kN-1; i >= 0; i--)
536   {
537      double sum=x[i];
538      for (int j = i+1; j < kN; j++)
539         sum -= A(i,j)*x[j];
540      x[i] = sum / A(i,i);
541   }
542
543}
544
545template <unsigned m_N, unsigned _storage_N>
546ATTR_HOT nl_double matrix_solver_direct_t<m_N, _storage_N>::delta(
547      const nl_double * RESTRICT V)
548{
549   /* FIXME: Ideally we should also include currents (RHS) here. This would
550    * need a revaluation of the right hand side after voltages have been updated
551    * and thus belong into a different calculation. This applies to all solvers.
552    */
553
554   const unsigned iN = this->N();
555   nl_double cerr = 0;
556   for (unsigned i = 0; i < iN; i++)
557      cerr = std::max(cerr, nl_math::abs(V[i] - this->m_nets[i]->m_cur_Analog));
558   return cerr;
559}
560
561template <unsigned m_N, unsigned _storage_N>
562ATTR_HOT void matrix_solver_direct_t<m_N, _storage_N>::store(
563      const nl_double * RESTRICT V)
564{
565   for (unsigned i = 0, iN=N(); i < iN; i++)
566   {
567      this->m_nets[i]->m_cur_Analog = V[i];
568   }
569}
570
571template <unsigned m_N, unsigned _storage_N>
572ATTR_HOT nl_double matrix_solver_direct_t<m_N, _storage_N>::vsolve()
573{
574   this->solve_base(this);
575   return this->compute_next_timestep();
576}
577
578
579template <unsigned m_N, unsigned _storage_N>
580ATTR_HOT int matrix_solver_direct_t<m_N, _storage_N>::solve_non_dynamic(ATTR_UNUSED const bool newton_raphson)
581{
582   nl_double new_V[_storage_N]; // = { 0.0 };
583
584   this->LE_back_subst(new_V);
585
586   if (newton_raphson)
587   {
588      nl_double err = delta(new_V);
589
590      store(new_V);
591
592      return (err > this->m_params.m_accuracy) ? 2 : 1;
593   }
594   else
595   {
596      store(new_V);
597      return 1;
598   }
599}
600
601template <unsigned m_N, unsigned _storage_N>
602ATTR_HOT inline int matrix_solver_direct_t<m_N, _storage_N>::vsolve_non_dynamic(const bool newton_raphson)
603{
604   this->build_LE_A();
605   this->build_LE_RHS(m_last_RHS);
606
607   for (unsigned i=0, iN=N(); i < iN; i++)
608      m_RHS[i] = m_last_RHS[i];
609
610   this->LE_solve();
611
612   return this->solve_non_dynamic(newton_raphson);
613}
614
615template <unsigned m_N, unsigned _storage_N>
616matrix_solver_direct_t<m_N, _storage_N>::matrix_solver_direct_t(const solver_parameters_t *params, const int size)
617: matrix_solver_t(GAUSSIAN_ELIMINATION, params)
618, m_dim(size)
619, m_lp_fact(0)
620{
621   m_terms = palloc_array(terms_t *, N());
622   m_rails_temp = palloc_array(terms_t, N());
623
624   for (unsigned k = 0; k < N(); k++)
625   {
626      m_terms[k] = palloc(terms_t);
627      m_last_RHS[k] = 0.0;
628      m_last_V[k] = 0.0;
629   }
630}
631
632template <unsigned m_N, unsigned _storage_N>
633matrix_solver_direct_t<m_N, _storage_N>::matrix_solver_direct_t(const eSolverType type, const solver_parameters_t *params, const int size)
634: matrix_solver_t(type, params)
635, m_dim(size)
636, m_lp_fact(0)
637{
638   m_terms = palloc_array(terms_t *, N());
639   m_rails_temp = palloc_array(terms_t, N());
640
641   for (unsigned k = 0; k < N(); k++)
642   {
643      m_terms[k] = palloc(terms_t);
644      m_last_RHS[k] = 0.0;
645      m_last_V[k] = 0.0;
646   }
647}
648
649NETLIB_NAMESPACE_DEVICES_END()
650
651#endif /* NLD_MS_DIRECT_H_ */
trunk/src/lib/netlist/solver/nld_ms_gmres.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_ms_sor.h
5 *
6 * Generic successive over relaxation solver.
7 *
8 * Fow w==1 we will do the classic Gauss-Seidel approach
9 *
10 */
11
12#ifndef NLD_MS_GMRES_H_
13#define NLD_MS_GMRES_H_
14
15#include <algorithm>
16
17#include "solver/mat_cr.h"
18#include "solver/nld_ms_direct.h"
19#include "solver/nld_solver.h"
20#include "solver/vector_base.h"
21
22NETLIB_NAMESPACE_DEVICES_START()
23
24template <unsigned m_N, unsigned _storage_N>
25class matrix_solver_GMRES_t: public matrix_solver_direct_t<m_N, _storage_N>
26{
27public:
28
29   matrix_solver_GMRES_t(const solver_parameters_t *params, int size)
30      : matrix_solver_direct_t<m_N, _storage_N>(matrix_solver_t::GAUSS_SEIDEL, params, size)
31      , m_use_iLU_preconditioning(true)
32      , m_use_more_precise_stop_condition(false)
33      , m_accuracy_mult(1.0)
34      {
35         unsigned mr=this->N(); /* FIXME: maximum iterations locked in here */
36
37         for (unsigned i = 0; i < mr + 1; i++)
38            m_ht[i] = new nl_double[mr];
39
40         for (unsigned i = 0; i < this->N(); i++)
41            m_v[i] = new nl_double[_storage_N];
42
43      }
44
45   virtual ~matrix_solver_GMRES_t()
46   {
47      unsigned mr=this->N(); /* FIXME: maximum iterations locked in here */
48
49      for (unsigned i = 0; i < mr + 1; i++)
50         delete[] m_ht[i];
51
52      for (unsigned i = 0; i < this->N(); i++)
53         delete[] m_v[i];
54   }
55
56   virtual void vsetup(analog_net_t::list_t &nets);
57   ATTR_HOT virtual int vsolve_non_dynamic(const bool newton_raphson);
58protected:
59   ATTR_HOT virtual nl_double vsolve();
60
61private:
62
63   int solve_ilu_gmres(nl_double * RESTRICT x, nl_double * RESTRICT rhs, const unsigned restart_max, const unsigned mr, nl_double accuracy);
64
65   plist_t<int> m_term_cr[_storage_N];
66
67   bool m_use_iLU_preconditioning;
68   bool m_use_more_precise_stop_condition;
69
70   mat_cr_t<_storage_N> mat;
71
72   nl_double m_A[_storage_N * _storage_N];
73   nl_double m_LU[_storage_N * _storage_N];
74
75   nl_double m_c[_storage_N + 1];  /* mr + 1 */
76   nl_double m_g[_storage_N + 1];  /* mr + 1 */
77   nl_double * RESTRICT m_ht[_storage_N + 1];  /* (mr + 1), mr */
78   nl_double m_s[_storage_N];     /* mr + 1 */
79   nl_double * RESTRICT m_v[_storage_N + 1];      /*(mr + 1), n */
80   //double m_y[_storage_N];       /* mr + 1 */
81
82   nl_double m_accuracy_mult; // FXIME: Save state
83};
84
85// ----------------------------------------------------------------------------------------
86// matrix_solver - GMRES
87// ----------------------------------------------------------------------------------------
88
89template <unsigned m_N, unsigned _storage_N>
90void matrix_solver_GMRES_t<m_N, _storage_N>::vsetup(analog_net_t::list_t &nets)
91{
92   matrix_solver_direct_t<m_N, _storage_N>::vsetup(nets);
93
94   unsigned nz = 0;
95   const unsigned iN = this->N();
96
97   for (unsigned k=0; k<iN; k++)
98   {
99      terms_t * RESTRICT row = this->m_terms[k];
100      mat.ia[k] = nz;
101
102      for (unsigned j=0; j<row->m_nz.size(); j++)
103      {
104         mat.ja[nz] = row->m_nz[j];
105         if (row->m_nz[j] == k)
106            mat.diag[k] = nz;
107         nz++;
108      }
109
110      /* build pointers into the compressed row format matrix for each terminal */
111
112      for (unsigned j=0; j< this->m_terms[k]->m_railstart;j++)
113      {
114         for (unsigned i = mat.ia[k]; i<nz; i++)
115            if (this->m_terms[k]->net_other()[j] == (int) mat.ja[i])
116            {
117               m_term_cr[k].add(i);
118               break;
119            }
120         nl_assert(m_term_cr[k].size() == this->m_terms[k]->m_railstart);
121      }
122   }
123
124   mat.ia[iN] = nz;
125   mat.nz_num = nz;
126}
127
128template <unsigned m_N, unsigned _storage_N>
129ATTR_HOT nl_double matrix_solver_GMRES_t<m_N, _storage_N>::vsolve()
130{
131   this->solve_base(this);
132   return this->compute_next_timestep();
133}
134
135template <unsigned m_N, unsigned _storage_N>
136ATTR_HOT inline int matrix_solver_GMRES_t<m_N, _storage_N>::vsolve_non_dynamic(const bool newton_raphson)
137{
138   const unsigned iN = this->N();
139
140   /* ideally, we could get an estimate for the spectral radius of
141    * Inv(D - L) * U
142    *
143    * and estimate using
144    *
145    * omega = 2.0 / (1.0 + nl_math::sqrt(1-rho))
146    */
147
148   //nz_num = 0;
149   ATTR_ALIGN nl_double RHS[_storage_N];
150   ATTR_ALIGN nl_double new_V[_storage_N];
151   ATTR_ALIGN nl_double l_V[_storage_N];
152
153   for (unsigned i=0, e=mat.nz_num; i<e; i++)
154      m_A[i] = 0.0;
155
156   for (unsigned k = 0; k < iN; k++)
157   {
158      nl_double gtot_t = 0.0;
159      nl_double RHS_t = 0.0;
160
161      const unsigned term_count = this->m_terms[k]->count();
162      const unsigned railstart = this->m_terms[k]->m_railstart;
163      const nl_double * const RESTRICT gt = this->m_terms[k]->gt();
164      const nl_double * const RESTRICT go = this->m_terms[k]->go();
165      const nl_double * const RESTRICT Idr = this->m_terms[k]->Idr();
166      const nl_double * const * RESTRICT other_cur_analog = this->m_terms[k]->other_curanalog();
167
168      l_V[k] = new_V[k] = this->m_nets[k]->m_cur_Analog;
169      for (unsigned i = 0; i < term_count; i++)
170      {
171         gtot_t = gtot_t + gt[i];
172         RHS_t = RHS_t + Idr[i];
173      }
174
175      for (unsigned i = railstart; i < term_count; i++)
176         RHS_t = RHS_t  + go[i] * *other_cur_analog[i];
177
178      RHS[k] = RHS_t;
179
180      // add diagonal element
181      m_A[mat.diag[k]] = gtot_t;
182
183      for (unsigned i = 0; i < railstart; i++)
184      {
185         const unsigned pi = m_term_cr[k][i];
186         m_A[pi] -= go[i];
187      }
188   }
189   mat.ia[iN] = mat.nz_num;
190
191   const nl_double accuracy = this->m_params.m_accuracy;
192#if 1
193   int mr = _storage_N;
194   if (_storage_N > 3 )
195      mr = (int) sqrt(iN);
196   mr = std::min(mr, this->m_params.m_gs_loops);
197   int iter = 4;
198   int gsl = solve_ilu_gmres(new_V, RHS, iter, mr, accuracy);
199   int failed = mr * iter;
200#else
201   int failed = 6;
202   //int gsl = tt_ilu_cr(new_V, RHS, failed, accuracy);
203   int gsl = tt_gs_cr(new_V, RHS, failed, accuracy);
204#endif
205   this->m_iterative_total += gsl;
206   this->m_stat_calculations++;
207
208   if (gsl>=failed)
209   {
210      //for (int k = 0; k < iN; k++)
211      //  this->m_nets[k]->m_cur_Analog = new_V[k];
212      // Fallback to direct solver ...
213      this->m_iterative_fail++;
214      return matrix_solver_direct_t<m_N, _storage_N>::vsolve_non_dynamic(newton_raphson);
215   }
216
217   if (newton_raphson)
218   {
219      nl_double err = 0;
220      for (unsigned k = 0; k < iN; k++)
221         err = std::max(nl_math::abs(l_V[k] - new_V[k]), err);
222
223      for (unsigned k = 0; k < iN; k++)
224         this->m_nets[k]->m_cur_Analog += 1.0 * (new_V[k] - this->m_nets[k]->m_cur_Analog);
225      if (err > accuracy)
226         return 2;
227      else
228         return 1;
229   }
230   else
231   {
232      for (unsigned k = 0; k < iN; k++)
233         this->m_nets[k]->m_cur_Analog = new_V[k];
234      return 1;
235   }
236}
237
238static inline void givens_mult( const nl_double c, const nl_double s, nl_double * RESTRICT g0, nl_double * RESTRICT g1 )
239{
240   const double tg0 = c * *g0 - s * *g1;
241   const double tg1 = s * *g0 + c * *g1;
242
243   *g0 = tg0;
244   *g1 = tg1;
245}
246
247template <unsigned m_N, unsigned _storage_N>
248int matrix_solver_GMRES_t<m_N, _storage_N>::solve_ilu_gmres (nl_double * RESTRICT x, nl_double * RESTRICT rhs, const unsigned restart_max, const unsigned mr, nl_double accuracy)
249{
250   /*-------------------------------------------------------------------------
251    * The code below was inspired by code published by John Burkardt under
252    * the LPGL here:
253    *
254    * http://people.sc.fsu.edu/~jburkardt/cpp_src/mgmres/mgmres.html
255    *
256    * The code below was completely written from scratch based on the pseudo code
257    * found here:
258    *
259    * http://de.wikipedia.org/wiki/GMRES-Verfahren
260    *
261    * The Algorithm itself is described in
262    *
263    * Yousef Saad,
264    * Iterative Methods for Sparse Linear Systems,
265    * Second Edition,
266    * SIAM, 20003,
267    * ISBN: 0898715342,
268    * LC: QA188.S17.
269    *
270    *------------------------------------------------------------------------*/
271
272   unsigned itr_used = 0;
273   double rho_delta = 0.0;
274
275   const unsigned n = this->N();
276
277   if (m_use_iLU_preconditioning)
278      mat.incomplete_LU_factorization(m_A, m_LU);
279
280   if (m_use_more_precise_stop_condition)
281   {
282      /* derive residual for a given delta x
283       *
284       * LU y = A dx
285       *
286       * ==> rho / accuracy = sqrt(y * y)
287       *
288       * This approach will approximate the iterative stop condition
289       * based |xnew - xold| pretty precisely. But it is slow, or expressed
290       * differently: The invest doesn't pay off.
291       * Therefore we use the approach in the else part.
292       */
293      nl_double t[_storage_N];
294      nl_double Ax[_storage_N];
295      vec_set(n, accuracy, t);
296      mat.mult_vec(m_A, t, Ax);
297      mat.solveLUx(m_LU, Ax);
298
299      const nl_double rho_to_accuracy = std::sqrt(vecmult2(n, Ax)) / accuracy;
300
301      rho_delta = accuracy * rho_to_accuracy;
302   }
303   else
304      rho_delta = accuracy * std::sqrt((double) n) * m_accuracy_mult;
305
306   for (unsigned itr = 0; itr < restart_max; itr++)
307   {
308      unsigned last_k = mr;
309      nl_double mu;
310      nl_double rho;
311
312      nl_double Ax[_storage_N];
313      nl_double residual[_storage_N];
314
315      mat.mult_vec(m_A, x, Ax);
316
317      vec_sub(n, rhs, Ax, residual);
318
319      if (m_use_iLU_preconditioning)
320      {
321         mat.solveLUx(m_LU, residual);
322      }
323
324      rho = std::sqrt(vecmult2(n, residual));
325
326      vec_mult_scalar(n, residual, NL_FCONST(1.0) / rho, m_v[0]);
327
328      vec_set(mr+1, NL_FCONST(0.0), m_g);
329      m_g[0] = rho;
330
331      for (unsigned i = 0; i < mr; i++)
332         vec_set(mr + 1, NL_FCONST(0.0), m_ht[i]);
333
334      for (unsigned k = 0; k < mr; k++)
335      {
336         const unsigned k1 = k + 1;
337
338         mat.mult_vec(m_A, m_v[k], m_v[k1]);
339
340         if (m_use_iLU_preconditioning)
341            mat.solveLUx(m_LU, m_v[k1]);
342
343         for (unsigned j = 0; j <= k; j++)
344         {
345            m_ht[j][k] = vecmult(n, m_v[k1], m_v[j]);
346            vec_add_mult_scalar(n, m_v[j], -m_ht[j][k], m_v[k1]);
347         }
348         m_ht[k1][k] = std::sqrt(vecmult2(n, m_v[k1]));
349
350         if (m_ht[k1][k] != 0.0)
351            vec_scale(n, m_v[k1], NL_FCONST(1.0) / m_ht[k1][k]);
352
353         for (unsigned j = 0; j < k; j++)
354            givens_mult(m_c[j], m_s[j], &m_ht[j][k], &m_ht[j+1][k]);
355
356         mu = std::sqrt(std::pow(m_ht[k][k], 2) + std::pow(m_ht[k1][k], 2));
357
358         m_c[k] = m_ht[k][k] / mu;
359         m_s[k] = -m_ht[k1][k] / mu;
360         m_ht[k][k] = m_c[k] * m_ht[k][k] - m_s[k] * m_ht[k1][k];
361         m_ht[k1][k] = 0.0;
362
363         givens_mult(m_c[k], m_s[k], &m_g[k], &m_g[k1]);
364
365         rho = std::abs(m_g[k1]);
366
367         itr_used = itr_used + 1;
368
369         if (rho <= rho_delta)
370         {
371            last_k = k;
372            break;
373         }
374      }
375
376      if (last_k >= mr)
377         /* didn't converge within accuracy */
378         last_k = mr - 1;
379
380      nl_double m_y[_storage_N + 1];
381
382      /* Solve the system H * y = g */
383      /* x += m_v[j] * m_y[j]       */
384      for (int i = last_k; i >= 0; i--)
385      {
386         double tmp = m_g[i];
387         for (unsigned j = i + 1; j <= last_k; j++)
388         {
389            tmp -= m_ht[i][j] * m_y[j];
390         }
391         m_y[i] = tmp / m_ht[i][i];
392      }
393
394      for (unsigned i = 0; i <= last_k; i++)
395         vec_add_mult_scalar(n, m_v[i], m_y[i], x);
396
397#if 1
398      if (rho <= rho_delta)
399      {
400         break;
401      }
402#else
403      /* we try to approximate the x difference between to steps using m_v[last_k] */
404
405      double xdelta = m_y[last_k] * vec_maxabs(n, m_v[last_k]);
406      if (xdelta < accuracy)
407      {
408         if (m_accuracy_mult < 16384.0)
409            m_accuracy_mult = m_accuracy_mult * 2.0;
410         break;
411      }
412      else
413         m_accuracy_mult = m_accuracy_mult / 2.0;
414
415#endif
416   }
417
418   return itr_used;
419}
420
421
422
423NETLIB_NAMESPACE_DEVICES_END()
424
425#endif /* NLD_MS_GMRES_H_ */
trunk/src/lib/netlist/solver/nld_ms_sor.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_ms_sor.h
5 *
6 * Generic successive over relaxation solver.
7 *
8 * Fow w==1 we will do the classic Gauss-Seidel approach
9 *
10 */
11
12#ifndef NLD_MS_SOR_H_
13#define NLD_MS_SOR_H_
14
15#include <algorithm>
16
17#include "solver/nld_ms_direct.h"
18#include "solver/nld_solver.h"
19
20NETLIB_NAMESPACE_DEVICES_START()
21
22template <unsigned m_N, unsigned _storage_N>
23class matrix_solver_SOR_t: public matrix_solver_direct_t<m_N, _storage_N>
24{
25public:
26
27   matrix_solver_SOR_t(const solver_parameters_t *params, int size)
28      : matrix_solver_direct_t<m_N, _storage_N>(matrix_solver_t::GAUSS_SEIDEL, params, size)
29      , m_lp_fact(0)
30      {
31      }
32
33   virtual ~matrix_solver_SOR_t() {}
34
35   virtual void vsetup(analog_net_t::list_t &nets);
36   ATTR_HOT virtual int vsolve_non_dynamic(const bool newton_raphson);
37protected:
38   ATTR_HOT virtual nl_double vsolve();
39
40private:
41   nl_double m_lp_fact;
42};
43
44// ----------------------------------------------------------------------------------------
45// matrix_solver - Gauss - Seidel
46// ----------------------------------------------------------------------------------------
47
48
49template <unsigned m_N, unsigned _storage_N>
50void matrix_solver_SOR_t<m_N, _storage_N>::vsetup(analog_net_t::list_t &nets)
51{
52   matrix_solver_direct_t<m_N, _storage_N>::vsetup(nets);
53   this->save(NLNAME(m_lp_fact));
54}
55
56template <unsigned m_N, unsigned _storage_N>
57ATTR_HOT nl_double matrix_solver_SOR_t<m_N, _storage_N>::vsolve()
58{
59   this->solve_base(this);
60   return this->compute_next_timestep();
61}
62
63template <unsigned m_N, unsigned _storage_N>
64ATTR_HOT inline int matrix_solver_SOR_t<m_N, _storage_N>::vsolve_non_dynamic(const bool newton_raphson)
65{
66   const unsigned iN = this->N();
67   bool resched = false;
68   int  resched_cnt = 0;
69
70   /* ideally, we could get an estimate for the spectral radius of
71    * Inv(D - L) * U
72    *
73    * and estimate using
74    *
75    * omega = 2.0 / (1.0 + nl_math::sqrt(1-rho))
76    */
77
78   const nl_double ws = this->m_params.m_sor;
79
80   ATTR_ALIGN nl_double w[_storage_N];
81   ATTR_ALIGN nl_double one_m_w[_storage_N];
82   ATTR_ALIGN nl_double RHS[_storage_N];
83   ATTR_ALIGN nl_double new_V[_storage_N];
84
85   for (unsigned k = 0; k < iN; k++)
86   {
87      nl_double gtot_t = 0.0;
88      nl_double gabs_t = 0.0;
89      nl_double RHS_t = 0.0;
90
91      const unsigned term_count = this->m_terms[k]->count();
92      const nl_double * const RESTRICT gt = this->m_terms[k]->gt();
93      const nl_double * const RESTRICT go = this->m_terms[k]->go();
94      const nl_double * const RESTRICT Idr = this->m_terms[k]->Idr();
95      const nl_double * const *other_cur_analog = this->m_terms[k]->other_curanalog();
96
97      new_V[k] = this->m_nets[k]->m_cur_Analog;
98
99      for (unsigned i = 0; i < term_count; i++)
100      {
101         gtot_t = gtot_t + gt[i];
102         RHS_t = RHS_t + Idr[i];
103      }
104
105      for (unsigned i = this->m_terms[k]->m_railstart; i < term_count; i++)
106         RHS_t = RHS_t  + go[i] * *other_cur_analog[i];
107
108      RHS[k] = RHS_t;
109
110      if (USE_GABS)
111      {
112         for (unsigned i = 0; i < term_count; i++)
113            gabs_t = gabs_t + nl_math::abs(go[i]);
114
115         gabs_t *= NL_FCONST(0.5); // derived by try and error
116         if (gabs_t <= gtot_t)
117         {
118            w[k] = ws / gtot_t;
119            one_m_w[k] = NL_FCONST(1.0) - ws;
120         }
121         else
122         {
123            w[k] = NL_FCONST(1.0) / (gtot_t + gabs_t);
124            one_m_w[k] = NL_FCONST(1.0) - NL_FCONST(1.0) * gtot_t / (gtot_t + gabs_t);
125         }
126      }
127      else
128      {
129         w[k] = ws / gtot_t;
130         one_m_w[k] = NL_FCONST(1.0) - ws;
131      }
132   }
133
134   const nl_double accuracy = this->m_params.m_accuracy;
135
136   /* uncommenting the line below will force dynamic updates every X iterations
137    * althought the system has not converged yet. This is a proof of concept,
138    * 91glub
139    *
140    */
141   const bool interleaved_dynamic_updates = false;
142   //const bool interleaved_dynamic_updates = newton_raphson;
143
144   do {
145      resched = false;
146      nl_double err = 0;
147      for (unsigned k = 0; k < iN; k++)
148      {
149         const int * RESTRICT net_other = this->m_terms[k]->net_other();
150         const unsigned railstart = this->m_terms[k]->m_railstart;
151         const nl_double * RESTRICT go = this->m_terms[k]->go();
152
153         nl_double Idrive = 0.0;
154         for (unsigned i = 0; i < railstart; i++)
155            Idrive = Idrive + go[i] * new_V[net_other[i]];
156
157         const nl_double new_val = new_V[k] * one_m_w[k] + (Idrive + RHS[k]) * w[k];
158
159         err = std::max(nl_math::abs(new_val - new_V[k]), err);
160         new_V[k] = new_val;
161      }
162
163      if (err > accuracy)
164         resched = true;
165
166      resched_cnt++;
167   //} while (resched && (resched_cnt < this->m_params.m_gs_loops));
168   } while (resched && ((!interleaved_dynamic_updates && resched_cnt < this->m_params.m_gs_loops) || (interleaved_dynamic_updates && resched_cnt < 5 )));
169
170   this->m_iterative_total += resched_cnt;
171   this->m_stat_calculations++;
172
173   if (resched && !interleaved_dynamic_updates)
174   {
175      // Fallback to direct solver ...
176      this->m_iterative_fail++;
177      return matrix_solver_direct_t<m_N, _storage_N>::vsolve_non_dynamic(newton_raphson);
178   }
179
180   if (interleaved_dynamic_updates)
181   {
182      for (unsigned k = 0; k < iN; k++)
183         this->m_nets[k]->m_cur_Analog += 1.0 * (new_V[k] - this->m_nets[k]->m_cur_Analog);
184   }
185   else
186   {
187      for (unsigned k = 0; k < iN; k++)
188         this->m_nets[k]->m_cur_Analog = new_V[k];
189   }
190
191   return resched_cnt;
192}
193
194NETLIB_NAMESPACE_DEVICES_END()
195
196#endif /* NLD_MS_SOR_H_ */
trunk/src/lib/netlist/solver/nld_ms_sor_mat.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_ms_sor.h
5 *
6 * Generic successive over relaxation solver.
7 *
8 * Fow w==1 we will do the classic Gauss-Seidel approach
9 *
10 */
11
12#ifndef NLD_MS_SOR_MAT_H_
13#define NLD_MS_SOR_MAT_H_
14
15#include <algorithm>
16
17#include "solver/nld_ms_direct.h"
18#include "solver/nld_solver.h"
19
20NETLIB_NAMESPACE_DEVICES_START()
21
22template <unsigned m_N, unsigned _storage_N>
23class matrix_solver_SOR_mat_t: public matrix_solver_direct_t<m_N, _storage_N>
24{
25public:
26
27   matrix_solver_SOR_mat_t(const solver_parameters_t *params, int size)
28      : matrix_solver_direct_t<m_N, _storage_N>(matrix_solver_t::GAUSS_SEIDEL, params, size)
29      , m_omega(params->m_sor)
30      , m_lp_fact(0)
31      , m_gs_fail(0)
32      , m_gs_total(0)
33      {
34      }
35
36   virtual ~matrix_solver_SOR_mat_t() {}
37
38   virtual void vsetup(analog_net_t::list_t &nets);
39
40   ATTR_HOT inline int vsolve_non_dynamic(const bool newton_raphson);
41protected:
42   ATTR_HOT virtual nl_double vsolve();
43
44private:
45   nl_double m_Vdelta[_storage_N];
46
47   nl_double m_omega;
48   nl_double m_lp_fact;
49   int m_gs_fail;
50   int m_gs_total;
51};
52
53// ----------------------------------------------------------------------------------------
54// matrix_solver - Gauss - Seidel
55// ----------------------------------------------------------------------------------------
56
57template <unsigned m_N, unsigned _storage_N>
58void matrix_solver_SOR_mat_t<m_N, _storage_N>::vsetup(analog_net_t::list_t &nets)
59{
60   matrix_solver_direct_t<m_N, _storage_N>::vsetup(nets);
61   this->save(NLNAME(m_omega));
62   this->save(NLNAME(m_lp_fact));
63   this->save(NLNAME(m_gs_fail));
64   this->save(NLNAME(m_gs_total));
65   this->save(NLNAME(m_Vdelta));
66}
67
68
69template <unsigned m_N, unsigned _storage_N>
70ATTR_HOT nl_double matrix_solver_SOR_mat_t<m_N, _storage_N>::vsolve()
71{
72   /*
73    * enable linear prediction on first newton pass
74    */
75
76   if (USE_LINEAR_PREDICTION)
77      for (unsigned k = 0; k < this->N(); k++)
78      {
79         this->m_last_V[k] = this->m_nets[k]->m_cur_Analog;
80         this->m_nets[k]->m_cur_Analog = this->m_nets[k]->m_cur_Analog + this->m_Vdelta[k] * this->current_timestep() * m_lp_fact;
81      }
82   else
83      for (unsigned k = 0; k < this->N(); k++)
84      {
85         this->m_last_V[k] = this->m_nets[k]->m_cur_Analog;
86      }
87
88   this->solve_base(this);
89
90   if (USE_LINEAR_PREDICTION)
91   {
92      nl_double sq = 0;
93      nl_double sqo = 0;
94      const nl_double rez_cts = 1.0 / this->current_timestep();
95      for (unsigned k = 0; k < this->N(); k++)
96      {
97         const analog_net_t *n = this->m_nets[k];
98         const nl_double nv = (n->m_cur_Analog - this->m_last_V[k]) * rez_cts ;
99         sq += nv * nv;
100         sqo += this->m_Vdelta[k] * this->m_Vdelta[k];
101         this->m_Vdelta[k] = nv;
102      }
103
104      // FIXME: used to be 1e90, but this would not be compatible with float
105      if (sqo > NL_FCONST(1e-20))
106         m_lp_fact = std::min(nl_math::sqrt(sq/sqo), (nl_double) 2.0);
107      else
108         m_lp_fact = NL_FCONST(0.0);
109   }
110
111
112   return this->compute_next_timestep();
113}
114
115template <unsigned m_N, unsigned _storage_N>
116ATTR_HOT inline int matrix_solver_SOR_mat_t<m_N, _storage_N>::vsolve_non_dynamic(const bool newton_raphson)
117{
118   /* The matrix based code looks a lot nicer but actually is 30% slower than
119    * the optimized code which works directly on the data structures.
120    * Need something like that for gaussian elimination as well.
121    */
122
123
124   ATTR_ALIGN nl_double new_v[_storage_N] = { 0.0 };
125   const unsigned iN = this->N();
126
127   bool resched = false;
128
129   int  resched_cnt = 0;
130
131   this->build_LE_A();
132   this->build_LE_RHS(this->m_RHS);
133
134#if 0
135   static int ws_cnt = 0;
136   ws_cnt++;
137   if (1 && ws_cnt % 200 == 0)
138   {
139      // update omega
140      nl_double lambdaN = 0;
141      nl_double lambda1 = 1e9;
142      for (int k = 0; k < iN; k++)
143      {
144   #if 0
145         nl_double akk = nl_math::abs(this->m_A[k][k]);
146         if ( akk > lambdaN)
147            lambdaN = akk;
148         if (akk < lambda1)
149            lambda1 = akk;
150   #else
151         nl_double akk = nl_math::abs(this->m_A[k][k]);
152         nl_double s = 0.0;
153         for (int i=0; i<iN; i++)
154            s = s + nl_math::abs(this->m_A[k][i]);
155         akk = s / akk - 1.0;
156         if ( akk > lambdaN)
157            lambdaN = akk;
158         if (akk < lambda1)
159            lambda1 = akk;
160   #endif
161      }
162      //printf("lambda: %f %f\n", lambda, 2.0 / (1.0 + 2 * sqrt(lambda)) );
163
164      //ws = 2.0 / (2.0 - lambdaN - lambda1);
165      m_omega = 2.0 / (2.0 - lambda1);
166      //printf("%f %f %f\n", m_omega, lambda1, lambdaN);
167   }
168#endif
169
170   for (unsigned k = 0; k < iN; k++)
171      new_v[k] = this->m_nets[k]->m_cur_Analog;
172
173   do {
174      resched = false;
175      nl_double cerr = 0.0;
176
177      for (unsigned k = 0; k < iN; k++)
178      {
179         nl_double Idrive = 0;
180
181         const unsigned *p = this->m_terms[k]->m_nz.data();
182         const unsigned e = this->m_terms[k]->m_nz.size();
183
184         for (unsigned i = 0; i < e; i++)
185            Idrive = Idrive + this->A(k,p[i]) * new_v[p[i]];
186
187         const nl_double delta = m_omega * (this->m_RHS[k] - Idrive) / this->A(k,k);
188         cerr = std::max(cerr, nl_math::abs(delta));
189         new_v[k] += delta;
190      }
191
192      if (cerr > this->m_params.m_accuracy)
193      {
194         resched = true;
195      }
196      resched_cnt++;
197   } while (resched && (resched_cnt < this->m_params.m_gs_loops));
198
199   this->m_stat_calculations++;
200   this->m_gs_total += resched_cnt;
201
202   if (resched)
203   {
204      //this->netlist().warning("Falling back to direct solver .. Consider increasing RESCHED_LOOPS");
205      this->m_gs_fail++;
206
207      this->LE_solve();
208      return matrix_solver_direct_t<m_N, _storage_N>::solve_non_dynamic(newton_raphson);
209   }
210   else {
211      this->store(new_v);
212      return resched_cnt;
213   }
214
215}
216
217NETLIB_NAMESPACE_DEVICES_END()
218
219#endif /* NLD_MS_GAUSS_SEIDEL_H_ */
trunk/src/lib/netlist/solver/nld_solver.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_solver.c
5 *
6 */
7
8/* Commented out for now. Relatively low number of terminals / nets make
9 * the vectorizations fast-math enables pretty expensive
10 */
11
12// for now, make buggy GCC/Mingw STFU about I64FMT
13#if (defined(__MINGW32__) && (__GNUC__ >= 5))
14#pragma GCC diagnostic push
15#pragma GCC diagnostic ignored "-Wformat"
16#pragma GCC diagnostic ignored "-Wformat-extra-args"
17#endif
18
19
20#if 0
21#pragma GCC optimize "-ffast-math"
22//#pragma GCC optimize "-ftree-parallelize-loops=4"
23#pragma GCC optimize "-funroll-loops"
24#pragma GCC optimize "-funswitch-loops"
25#pragma GCC optimize "-fvariable-expansion-in-unroller"
26#pragma GCC optimize "-funsafe-loop-optimizations"
27#pragma GCC optimize "-fvect-cost-model"
28#pragma GCC optimize "-fvariable-expansion-in-unroller"
29#pragma GCC optimize "-ftree-loop-if-convert-stores"
30#pragma GCC optimize "-ftree-loop-distribution"
31#pragma GCC optimize "-ftree-loop-im"
32#pragma GCC optimize "-ftree-loop-ivcanon"
33#pragma GCC optimize "-fivopts"
34#endif
35
36#include <iostream>
37#include <algorithm>
38#include "nld_solver.h"
39#if 1
40#include "nld_ms_direct.h"
41#else
42#include "nld_ms_direct_lu.h"
43#endif
44#include "nld_ms_direct1.h"
45#include "nld_ms_direct2.h"
46#include "nld_ms_sor.h"
47#include "nld_ms_sor_mat.h"
48#include "nld_ms_gmres.h"
49//#include "nld_twoterm.h"
50#include "nl_lists.h"
51
52#if HAS_OPENMP
53#include "omp.h"
54#endif
55
56NETLIB_NAMESPACE_DEVICES_START()
57
58ATTR_COLD void terms_t::add(terminal_t *term, int net_other, bool sorted)
59{
60   if (sorted)
61      for (unsigned i=0; i < m_net_other.size(); i++)
62      {
63         if (m_net_other[i] > net_other)
64         {
65            m_term.insert_at(term, i);
66            m_net_other.insert_at(net_other, i);
67            m_gt.insert_at(0.0, i);
68            m_go.insert_at(0.0, i);
69            m_Idr.insert_at(0.0, i);
70            m_other_curanalog.insert_at(NULL, i);
71            return;
72         }
73      }
74   m_term.add(term);
75   m_net_other.add(net_other);
76   m_gt.add(0.0);
77   m_go.add(0.0);
78   m_Idr.add(0.0);
79   m_other_curanalog.add(NULL);
80}
81
82ATTR_COLD void terms_t::set_pointers()
83{
84   for (unsigned i = 0; i < count(); i++)
85   {
86      m_term[i]->m_gt1 = &m_gt[i];
87      m_term[i]->m_go1 = &m_go[i];
88      m_term[i]->m_Idr1 = &m_Idr[i];
89      m_other_curanalog[i] = &m_term[i]->m_otherterm->net().as_analog().m_cur_Analog;
90   }
91}
92
93// ----------------------------------------------------------------------------------------
94// matrix_solver
95// ----------------------------------------------------------------------------------------
96
97ATTR_COLD matrix_solver_t::matrix_solver_t(const eSolverType type, const solver_parameters_t *params)
98: m_stat_calculations(0),
99   m_stat_newton_raphson(0),
100   m_stat_vsolver_calls(0),
101   m_iterative_fail(0),
102   m_iterative_total(0),
103   m_params(*params),
104   m_cur_ts(0),
105   m_type(type)
106{
107}
108
109ATTR_COLD matrix_solver_t::~matrix_solver_t()
110{
111   m_inps.clear_and_free();
112}
113
114ATTR_COLD void matrix_solver_t::setup(analog_net_t::list_t &nets)
115{
116   log().debug("New solver setup\n");
117
118   m_nets.clear();
119
120   for (std::size_t k = 0; k < nets.size(); k++)
121   {
122      m_nets.add(nets[k]);
123   }
124
125   for (std::size_t k = 0; k < nets.size(); k++)
126   {
127      log().debug("setting up net\n");
128
129      analog_net_t *net = nets[k];
130
131      net->m_solver = this;
132
133      for (std::size_t i = 0; i < net->m_core_terms.size(); i++)
134      {
135         core_terminal_t *p = net->m_core_terms[i];
136         log().debug("{1} {2} {3}\n", p->name(), net->name(), (int) net->isRailNet());
137         switch (p->type())
138         {
139            case terminal_t::TERMINAL:
140               switch (p->device().family())
141               {
142                  case device_t::CAPACITOR:
143                     if (!m_step_devices.contains(&p->device()))
144                        m_step_devices.add(&p->device());
145                     break;
146                  case device_t::BJT_EB:
147                  case device_t::DIODE:
148                  case device_t::LVCCS:
149                  case device_t::BJT_SWITCH:
150                     log().debug("found BJT/Diode/LVCCS\n");
151                     if (!m_dynamic_devices.contains(&p->device()))
152                        m_dynamic_devices.add(&p->device());
153                     break;
154                  default:
155                     break;
156               }
157               {
158                  terminal_t *pterm = dynamic_cast<terminal_t *>(p);
159                  add_term(k, pterm);
160               }
161               log().debug("Added terminal\n");
162               break;
163            case terminal_t::INPUT:
164               {
165                  analog_output_t *net_proxy_output = NULL;
166                  for (std::size_t i = 0; i < m_inps.size(); i++)
167                     if (m_inps[i]->m_proxied_net == &p->net().as_analog())
168                     {
169                        net_proxy_output = m_inps[i];
170                        break;
171                     }
172
173                  if (net_proxy_output == NULL)
174                  {
175                     net_proxy_output = palloc(analog_output_t);
176                     net_proxy_output->init_object(*this, this->name() + "." + pfmt("m{1}")(m_inps.size()));
177                     m_inps.add(net_proxy_output);
178                     net_proxy_output->m_proxied_net = &p->net().as_analog();
179                  }
180                  net_proxy_output->net().register_con(*p);
181                  // FIXME: repeated
182                  net_proxy_output->net().rebuild_list();
183                  log().debug("Added input\n");
184               }
185               break;
186            default:
187               log().fatal("unhandled element found\n");
188               break;
189         }
190      }
191      log().debug("added net with {1} populated connections\n", net->m_core_terms.size());
192   }
193
194}
195
196
197ATTR_HOT void matrix_solver_t::update_inputs()
198{
199   // avoid recursive calls. Inputs are updated outside this call
200   for (std::size_t i=0; i<m_inps.size(); i++)
201      m_inps[i]->set_Q(m_inps[i]->m_proxied_net->m_cur_Analog);
202}
203
204ATTR_HOT void matrix_solver_t::update_dynamic()
205{
206   /* update all non-linear devices  */
207   for (std::size_t i=0; i < m_dynamic_devices.size(); i++)
208      m_dynamic_devices[i]->update_terminals();
209}
210
211ATTR_COLD void matrix_solver_t::start()
212{
213   register_output("Q_sync", m_Q_sync);
214   register_input("FB_sync", m_fb_sync);
215   connect_direct(m_fb_sync, m_Q_sync);
216
217   save(NLNAME(m_last_step));
218   save(NLNAME(m_cur_ts));
219   save(NLNAME(m_stat_calculations));
220   save(NLNAME(m_stat_newton_raphson));
221   save(NLNAME(m_stat_vsolver_calls));
222   save(NLNAME(m_iterative_fail));
223   save(NLNAME(m_iterative_total));
224
225}
226
227ATTR_COLD void matrix_solver_t::reset()
228{
229   m_last_step = netlist_time::zero;
230}
231
232ATTR_COLD void matrix_solver_t::update()
233{
234   const nl_double new_timestep = solve();
235
236   if (m_params.m_dynamic && is_timestep() && new_timestep > 0)
237      m_Q_sync.net().reschedule_in_queue(netlist_time::from_double(new_timestep));
238}
239
240ATTR_COLD void matrix_solver_t::update_forced()
241{
242   ATTR_UNUSED const nl_double new_timestep = solve();
243
244   if (m_params.m_dynamic && is_timestep())
245      m_Q_sync.net().reschedule_in_queue(netlist_time::from_double(m_params.m_min_timestep));
246}
247
248ATTR_HOT void matrix_solver_t::step(const netlist_time delta)
249{
250   const nl_double dd = delta.as_double();
251   for (std::size_t k=0; k < m_step_devices.size(); k++)
252      m_step_devices[k]->step_time(dd);
253}
254
255template<class C >
256void matrix_solver_t::solve_base(C *p)
257{
258   m_stat_vsolver_calls++;
259   if (is_dynamic())
260   {
261      int this_resched;
262      int newton_loops = 0;
263      do
264      {
265         update_dynamic();
266         // Gauss-Seidel will revert to Gaussian elemination if steps exceeded.
267         this_resched = p->vsolve_non_dynamic(true);
268         newton_loops++;
269      } while (this_resched > 1 && newton_loops < m_params.m_nr_loops);
270
271      m_stat_newton_raphson += newton_loops;
272      // reschedule ....
273      if (this_resched > 1 && !m_Q_sync.net().is_queued())
274      {
275         log().warning("NEWTON_LOOPS exceeded on net {1}... reschedule", this->name());
276         m_Q_sync.net().reschedule_in_queue(m_params.m_nt_sync_delay);
277      }
278   }
279   else
280   {
281      p->vsolve_non_dynamic(false);
282   }
283}
284
285ATTR_HOT nl_double matrix_solver_t::solve()
286{
287   const netlist_time now = netlist().time();
288   const netlist_time delta = now - m_last_step;
289
290   // We are already up to date. Avoid oscillations.
291   // FIXME: Make this a parameter!
292   if (delta < netlist_time::from_nsec(1)) // 20000
293      return -1.0;
294
295   /* update all terminals for new time step */
296   m_last_step = now;
297   m_cur_ts = delta.as_double();
298
299   step(delta);
300
301   const nl_double next_time_step = vsolve();
302
303   update_inputs();
304   return next_time_step;
305}
306
307ATTR_COLD int matrix_solver_t::get_net_idx(net_t *net)
308{
309   for (std::size_t k = 0; k < m_nets.size(); k++)
310      if (m_nets[k] == net)
311         return k;
312   return -1;
313}
314
315void matrix_solver_t::log_stats()
316{
317   if (this->m_stat_calculations != 0 && this->m_params.m_log_stats)
318   {
319      log().verbose("==============================================");
320      log().verbose("Solver {1}", this->name());
321      log().verbose("       ==> {1} nets", this->m_nets.size()); //, (*(*groups[i].first())->m_core_terms.first())->name());
322      log().verbose("       has {1} elements", this->is_dynamic() ? "dynamic" : "no dynamic");
323      log().verbose("       has {1} elements", this->is_timestep() ? "timestep" : "no timestep");
324      log().verbose("       {1:6.3} average newton raphson loops", (double) this->m_stat_newton_raphson / (double) this->m_stat_vsolver_calls);
325      log().verbose("       {1:10} invocations ({2:6} Hz)  {3:10} gs fails ({4:6.2} %) {5:6.3} average",
326            this->m_stat_calculations,
327            this->m_stat_calculations * 10 / (int) (this->netlist().time().as_double() * 10.0),
328            this->m_iterative_fail,
329            100.0 * (double) this->m_iterative_fail / (double) this->m_stat_calculations,
330            (double) this->m_iterative_total / (double) this->m_stat_calculations);
331   }
332}
333
334
335
336
337
338
339
340// ----------------------------------------------------------------------------------------
341// solver
342// ----------------------------------------------------------------------------------------
343
344
345
346NETLIB_START(solver)
347{
348   register_output("Q_step", m_Q_step);
349
350   register_param("SYNC_DELAY", m_sync_delay, NLTIME_FROM_NS(10).as_double());
351
352   register_param("FREQ", m_freq, 48000.0);
353
354
355   /* iteration parameters */
356   register_param("SOR_FACTOR", m_sor, 1.059);
357   register_param("ITERATIVE", m_iterative_solver, "SOR");
358   register_param("ACCURACY", m_accuracy, 1e-7);
359   register_param("GS_THRESHOLD", m_gs_threshold, 6);      // below this value, gaussian elimination is used
360   register_param("GS_LOOPS", m_gs_loops, 9);              // Gauss-Seidel loops
361
362   /* general parameters */
363   register_param("GMIN", m_gmin, NETLIST_GMIN_DEFAULT);
364   register_param("PIVOT", m_pivot, 0);                    // use pivoting - on supported solvers
365   register_param("NR_LOOPS", m_nr_loops, 250);            // Newton-Raphson loops
366   register_param("PARALLEL", m_parallel, 0);
367
368   /* automatic time step */
369   register_param("DYNAMIC_TS", m_dynamic, 0);
370   register_param("LTE", m_lte, 5e-5);                     // diff/timestep
371   register_param("MIN_TIMESTEP", m_min_timestep, 1e-6);   // nl_double timestep resolution
372
373   register_param("LOG_STATS", m_log_stats, 1);   // nl_double timestep resolution
374
375   // internal staff
376
377   register_input("FB_step", m_fb_step);
378   connect_late(m_fb_step, m_Q_step);
379
380}
381
382NETLIB_RESET(solver)
383{
384   for (std::size_t i = 0; i < m_mat_solvers.size(); i++)
385      m_mat_solvers[i]->reset();
386}
387
388
389NETLIB_UPDATE_PARAM(solver)
390{
391   //m_inc = time::from_hz(m_freq.Value());
392}
393
394NETLIB_STOP(solver)
395{
396   for (std::size_t i = 0; i < m_mat_solvers.size(); i++)
397      m_mat_solvers[i]->log_stats();
398}
399
400NETLIB_NAME(solver)::~NETLIB_NAME(solver)()
401{
402   m_mat_solvers.clear_and_free();
403}
404
405NETLIB_UPDATE(solver)
406{
407   if (m_params.m_dynamic)
408      return;
409
410   const std::size_t t_cnt = m_mat_solvers.size();
411
412#if HAS_OPENMP && USE_OPENMP
413   if (m_parallel.Value())
414   {
415      omp_set_num_threads(3);
416      //omp_set_dynamic(0);
417      #pragma omp parallel
418      {
419         #pragma omp for
420         for (int i = 0; i <  t_cnt; i++)
421            if (m_mat_solvers[i]->is_timestep())
422            {
423               // Ignore return value
424               ATTR_UNUSED const nl_double ts = m_mat_solvers[i]->solve();
425            }
426      }
427   }
428   else
429      for (int i = 0; i < t_cnt; i++)
430         if (m_mat_solvers[i]->is_timestep())
431         {
432            // Ignore return value
433            ATTR_UNUSED const nl_double ts = m_mat_solvers[i]->solve();
434         }
435#else
436   for (std::size_t i = 0; i < t_cnt; i++)
437   {
438      if (m_mat_solvers[i]->is_timestep())
439      {
440         // Ignore return value
441         ATTR_UNUSED const nl_double ts = m_mat_solvers[i]->solve();
442      }
443   }
444#endif
445
446   /* step circuit */
447   if (!m_Q_step.net().is_queued())
448   {
449      m_Q_step.net().push_to_queue(netlist_time::from_double(m_params.m_max_timestep));
450   }
451}
452
453template <int m_N, int _storage_N>
454matrix_solver_t * NETLIB_NAME(solver)::create_solver(int size, const bool use_specific)
455{
456   if (use_specific && m_N == 1)
457      return palloc(matrix_solver_direct1_t(&m_params));
458   else if (use_specific && m_N == 2)
459      return palloc(matrix_solver_direct2_t(&m_params));
460   else
461   {
462      if (size >= m_gs_threshold)
463      {
464         if (pstring("SOR_MAT").equals(m_iterative_solver))
465         {
466            typedef matrix_solver_SOR_mat_t<m_N,_storage_N> solver_mat;
467            return palloc(solver_mat(&m_params, size));
468         }
469         else if (pstring("SOR").equals(m_iterative_solver))
470         {
471            typedef matrix_solver_SOR_t<m_N,_storage_N> solver_GS;
472            return palloc(solver_GS(&m_params, size));
473         }
474         else if (pstring("GMRES").equals(m_iterative_solver))
475         {
476            typedef matrix_solver_GMRES_t<m_N,_storage_N> solver_GMRES;
477            return palloc(solver_GMRES(&m_params, size));
478         }
479         else
480         {
481            netlist().log().fatal("Unknown solver type: {1}\n", m_iterative_solver.Value());
482            return NULL;
483         }
484      }
485      else
486      {
487         typedef matrix_solver_direct_t<m_N,_storage_N> solver_D;
488         return palloc(solver_D(&m_params, size));
489      }
490   }
491}
492
493ATTR_COLD void NETLIB_NAME(solver)::post_start()
494{
495   analog_net_t::list_t groups[256];
496   int cur_group = -1;
497   const bool use_specific = true;
498
499   m_params.m_pivot = m_pivot.Value();
500   m_params.m_accuracy = m_accuracy.Value();
501   m_params.m_gs_loops = m_gs_loops.Value();
502   m_params.m_nr_loops = m_nr_loops.Value();
503   m_params.m_nt_sync_delay = netlist_time::from_double(m_sync_delay.Value());
504   m_params.m_lte = m_lte.Value();
505   m_params.m_sor = m_sor.Value();
506
507   m_params.m_min_timestep = m_min_timestep.Value();
508   m_params.m_dynamic = (m_dynamic.Value() == 1 ? true : false);
509   m_params.m_max_timestep = netlist_time::from_hz(m_freq.Value()).as_double();
510
511   if (m_params.m_dynamic)
512   {
513      m_params.m_max_timestep *= NL_FCONST(1000.0);
514   }
515   else
516   {
517      m_params.m_min_timestep = m_params.m_max_timestep;
518   }
519
520   // Override log statistics
521   pstring p = nl_util::environment("NL_STATS");
522   if (p != "")
523      m_params.m_log_stats = (bool) p.as_long();
524   else
525      m_params.m_log_stats = (bool) m_log_stats.Value();
526
527   netlist().log().verbose("Scanning net groups ...");
528   // determine net groups
529   for (std::size_t i=0; i<netlist().m_nets.size(); i++)
530   {
531      netlist().log().debug("processing {1}\n", netlist().m_nets[i]->name());
532      if (!netlist().m_nets[i]->isRailNet())
533      {
534         netlist().log().debug("   ==> not a rail net\n");
535         analog_net_t *n = &netlist().m_nets[i]->as_analog();
536         if (!n->already_processed(groups, cur_group))
537         {
538            cur_group++;
539            n->process_net(groups, cur_group);
540         }
541      }
542   }
543
544   // setup the solvers
545   netlist().log().verbose("Found {1} net groups in {2} nets\n", cur_group + 1, netlist().m_nets.size());
546   for (int i = 0; i <= cur_group; i++)
547   {
548      matrix_solver_t *ms;
549      std::size_t net_count = groups[i].size();
550
551      switch (net_count)
552      {
553         case 1:
554            ms = create_solver<1,1>(1, use_specific);
555            break;
556         case 2:
557            ms = create_solver<2,2>(2, use_specific);
558            break;
559         case 3:
560            ms = create_solver<3,3>(3, use_specific);
561            break;
562         case 4:
563            ms = create_solver<4,4>(4, use_specific);
564            break;
565         case 5:
566            ms = create_solver<5,5>(5, use_specific);
567            break;
568         case 6:
569            ms = create_solver<6,6>(6, use_specific);
570            break;
571         case 7:
572            ms = create_solver<7,7>(7, use_specific);
573            break;
574         case 8:
575            ms = create_solver<8,8>(8, use_specific);
576            break;
577         case 10:
578            ms = create_solver<10,10>(10, use_specific);
579            break;
580         case 11:
581            ms = create_solver<11,11>(11, use_specific);
582            break;
583         case 12:
584            ms = create_solver<12,12>(12, use_specific);
585            break;
586         case 15:
587            ms = create_solver<15,15>(15, use_specific);
588            break;
589         case 31:
590            ms = create_solver<31,31>(31, use_specific);
591            break;
592         case 49:
593            ms = create_solver<49,49>(49, use_specific);
594            break;
595#if 0
596         case 87:
597            ms = create_solver<87,87>(87, use_specific);
598            break;
599#endif
600         default:
601            netlist().log().warning("No specific solver found for netlist of size {1}", (unsigned) net_count);
602            if (net_count <= 16)
603            {
604               ms = create_solver<0,16>(net_count, use_specific);
605            }
606            else if (net_count <= 32)
607            {
608               ms = create_solver<0,32>(net_count, use_specific);
609            }
610            else if (net_count <= 64)
611            {
612               ms = create_solver<0,64>(net_count, use_specific);
613            }
614            else
615               if (net_count <= 128)
616            {
617               ms = create_solver<0,128>(net_count, use_specific);
618            }
619            else
620            {
621               netlist().log().fatal("Encountered netgroup with > 128 nets");
622               ms = NULL; /* tease compilers */
623            }
624
625            break;
626      }
627
628      register_sub(pfmt("Solver_{1}")(m_mat_solvers.size()), *ms);
629
630      ms->vsetup(groups[i]);
631
632      m_mat_solvers.add(ms);
633
634      netlist().log().verbose("Solver {1}", ms->name());
635      netlist().log().verbose("       # {1} ==> {2} nets", i, groups[i].size());
636      netlist().log().verbose("       has {1} elements", ms->is_dynamic() ? "dynamic" : "no dynamic");
637      netlist().log().verbose("       has {1} elements", ms->is_timestep() ? "timestep" : "no timestep");
638      for (std::size_t j=0; j<groups[i].size(); j++)
639      {
640         netlist().log().verbose("Net {1}: {2}", j, groups[i][j]->name());
641         net_t *n = groups[i][j];
642         for (std::size_t k = 0; k < n->m_core_terms.size(); k++)
643         {
644            const core_terminal_t *p = n->m_core_terms[k];
645            netlist().log().verbose("   {1}", p->name());
646         }
647      }
648   }
649}
650
651NETLIB_NAMESPACE_DEVICES_END()
652
653#if (defined(__MINGW32__) && (__GNUC__ >= 5))
654#pragma GCC diagnostic pop
655#endif
trunk/src/lib/netlist/solver/nld_solver.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nld_solver.h
5 *
6 */
7
8#ifndef NLD_SOLVER_H_
9#define NLD_SOLVER_H_
10
11#include "nl_setup.h"
12#include "nl_base.h"
13
14//#define ATTR_ALIGNED(N) __attribute__((aligned(N)))
15#define ATTR_ALIGNED(N) ATTR_ALIGN
16
17#define SOLVER_VERBOSE_OUT(x) do {} while (0)
18//#define SOLVER_VERBOSE_OUT(x) printf x
19
20// ----------------------------------------------------------------------------------------
21// Macros
22// ----------------------------------------------------------------------------------------
23
24#define SOLVER(_name, _freq)                                                 \
25      NET_REGISTER_DEV(SOLVER, _name)                                      \
26      PARAM(_name.FREQ, _freq)
27
28// ----------------------------------------------------------------------------------------
29// solver
30// ----------------------------------------------------------------------------------------
31
32NETLIB_NAMESPACE_DEVICES_START()
33
34class NETLIB_NAME(solver);
35
36/* FIXME: these should become proper devices */
37
38struct solver_parameters_t
39{
40   int m_pivot;
41   nl_double m_accuracy;
42   nl_double m_lte;
43   nl_double m_min_timestep;
44   nl_double m_max_timestep;
45   nl_double m_sor;
46   bool m_dynamic;
47   int m_gs_loops;
48   int m_nr_loops;
49   netlist_time m_nt_sync_delay;
50   bool m_log_stats;
51};
52
53
54class terms_t
55{
56   P_PREVENT_COPYING(terms_t)
57
58   public:
59   ATTR_COLD terms_t() : m_railstart(0)
60   {}
61
62   ATTR_COLD void clear()
63   {
64      m_term.clear();
65      m_net_other.clear();
66      m_gt.clear();
67      m_go.clear();
68      m_Idr.clear();
69      m_other_curanalog.clear();
70   }
71
72   ATTR_COLD void add(terminal_t *term, int net_other, bool sorted);
73
74   ATTR_HOT inline unsigned count() { return m_term.size(); }
75
76   ATTR_HOT inline terminal_t **terms() { return m_term.data(); }
77   ATTR_HOT inline int *net_other() { return m_net_other.data(); }
78   ATTR_HOT inline nl_double *gt() { return m_gt.data(); }
79   ATTR_HOT inline nl_double *go() { return m_go.data(); }
80   ATTR_HOT inline nl_double *Idr() { return m_Idr.data(); }
81   ATTR_HOT inline nl_double **other_curanalog() { return m_other_curanalog.data(); }
82
83   ATTR_COLD void set_pointers();
84
85   unsigned m_railstart;
86
87   plist_t<unsigned> m_nz;   /* all non zero for multiplication */
88   plist_t<unsigned> m_nzrd; /* non zero right of the diagonal for elimination */
89   plist_t<unsigned> m_nzbd; /* non zero below of the diagonal for elimination */
90private:
91   plist_t<terminal_t *> m_term;
92   plist_t<int> m_net_other;
93   plist_t<nl_double> m_go;
94   plist_t<nl_double> m_gt;
95   plist_t<nl_double> m_Idr;
96   plist_t<nl_double *> m_other_curanalog;
97};
98
99class matrix_solver_t : public device_t
100{
101public:
102   typedef plist_t<matrix_solver_t *> list_t;
103   typedef core_device_t::list_t dev_list_t;
104
105   enum eSolverType
106   {
107      GAUSSIAN_ELIMINATION,
108      GAUSS_SEIDEL
109   };
110
111   ATTR_COLD matrix_solver_t(const eSolverType type, const solver_parameters_t *params);
112   virtual ~matrix_solver_t();
113
114   virtual void vsetup(analog_net_t::list_t &nets) = 0;
115
116   template<class C>
117   void solve_base(C *p);
118
119   ATTR_HOT nl_double solve();
120
121   ATTR_HOT inline bool is_dynamic() { return m_dynamic_devices.size() > 0; }
122   ATTR_HOT inline bool is_timestep() { return m_step_devices.size() > 0; }
123
124   ATTR_HOT void update_forced();
125   ATTR_HOT inline void update_after(const netlist_time after)
126   {
127      m_Q_sync.net().reschedule_in_queue(after);
128   }
129
130   /* netdevice functions */
131   ATTR_HOT  virtual void update();
132   virtual void start();
133   virtual void reset();
134
135   ATTR_COLD int get_net_idx(net_t *net);
136
137   inline eSolverType type() const { return m_type; }
138   plog_base<NL_DEBUG> &log() { return netlist().log(); }
139
140   virtual void log_stats();
141
142protected:
143
144   ATTR_COLD void setup(analog_net_t::list_t &nets);
145   ATTR_HOT void update_dynamic();
146
147   // should return next time step
148   ATTR_HOT virtual nl_double vsolve() = 0;
149
150   virtual void  add_term(int net_idx, terminal_t *term) = 0;
151
152   plist_t<analog_net_t *> m_nets;
153   plist_t<analog_output_t *> m_inps;
154
155   int m_stat_calculations;
156   int m_stat_newton_raphson;
157   int m_stat_vsolver_calls;
158   int m_iterative_fail;
159   int m_iterative_total;
160
161   const solver_parameters_t &m_params;
162
163   ATTR_HOT inline nl_double current_timestep() { return m_cur_ts; }
164private:
165
166   netlist_time m_last_step;
167   nl_double m_cur_ts;
168   dev_list_t m_step_devices;
169   dev_list_t m_dynamic_devices;
170
171   logic_input_t m_fb_sync;
172   logic_output_t m_Q_sync;
173
174   ATTR_HOT void step(const netlist_time delta);
175
176   ATTR_HOT void update_inputs();
177
178   const eSolverType m_type;
179};
180
181
182
183class NETLIB_NAME(solver) : public device_t
184{
185public:
186   NETLIB_NAME(solver)()
187   : device_t()    { }
188
189   virtual ~NETLIB_NAME(solver)();
190
191   ATTR_COLD void post_start();
192   ATTR_COLD void stop();
193
194   ATTR_HOT inline nl_double gmin() { return m_gmin.Value(); }
195
196protected:
197   ATTR_HOT void update();
198   ATTR_HOT void start();
199   ATTR_HOT void reset();
200   ATTR_HOT void update_param();
201
202   logic_input_t m_fb_step;
203   logic_output_t m_Q_step;
204
205   param_logic_t  m_pivot;
206   param_double_t m_freq;
207   param_double_t m_sync_delay;
208   param_double_t m_accuracy;
209   param_double_t m_gmin;
210   param_double_t m_lte;
211   param_double_t m_sor;
212   param_logic_t  m_dynamic;
213   param_double_t m_min_timestep;
214
215   param_str_t m_iterative_solver;
216   param_int_t m_nr_loops;
217   param_int_t m_gs_loops;
218   param_int_t m_gs_threshold;
219   param_int_t m_parallel;
220
221   param_logic_t  m_log_stats;
222
223   matrix_solver_t::list_t m_mat_solvers;
224private:
225
226   solver_parameters_t m_params;
227
228   template <int m_N, int _storage_N>
229   matrix_solver_t *create_solver(int size, bool use_specific);
230};
231
232NETLIB_NAMESPACE_DEVICES_END()
233
234#endif /* NLD_SOLVER_H_ */
trunk/src/lib/netlist/solver/vector_base.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * vector_base.h
5 *
6 * Base vector operations
7 *
8 */
9
10#ifndef VECTOR_BASE_H_
11#define VECTOR_BASE_H_
12
13#include <algorithm>
14#include "plib/pconfig.h"
15
16#if 0
17template <unsigned _storage_N>
18struct pvector
19{
20   pvector(unsigned size)
21   : m_N(size) { }
22
23   unsigned size() {
24      if (_storage_N)
25   }
26
27   double m_V[_storage_N];
28private:
29   unsigned m_N;
30};
31#endif
32
33#if !defined(__clang__) && !defined(_MSC_VER) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))
34#pragma GCC diagnostic push
35#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
36#endif
37
38template<typename T>
39inline void vec_set (const std::size_t n, const T &scalar, T * RESTRICT result)
40{
41   for ( std::size_t i = 0; i < n; i++ )
42      result[i] = scalar;
43}
44
45template<typename T>
46inline T vecmult (const std::size_t n, const T * RESTRICT a1, const T * RESTRICT a2 )
47{
48   T value = 0.0;
49   for ( std::size_t i = 0; i < n; i++ )
50      value = value + a1[i] * a2[i];
51   return value;
52}
53
54template<typename T>
55inline T vecmult2 (const std::size_t n, const T *a1)
56{
57   T value = 0.0;
58   for ( std::size_t i = 0; i < n; i++ )
59   {
60      const T temp = a1[i];
61      value = value + temp * temp;
62   }
63   return value;
64}
65
66template<typename T>
67inline void vec_mult_scalar (const std::size_t n, const T * RESTRICT v, const T scalar, T * RESTRICT result)
68{
69   for ( std::size_t i = 0; i < n; i++ )
70   {
71      result[i] = scalar * v[i];
72   }
73}
74
75template<typename T>
76inline void vec_add_mult_scalar (const std::size_t n, const T * RESTRICT v, const T scalar, T * RESTRICT result)
77{
78   for ( std::size_t i = 0; i < n; i++ )
79      result[i] += scalar * v[i];
80}
81
82inline void vec_add_ip(const std::size_t n, const double * RESTRICT v, double * RESTRICT result)
83{
84   for ( std::size_t i = 0; i < n; i++ )
85      result[i] += v[i];
86}
87
88template<typename T>
89inline void vec_sub(const std::size_t n, const T * RESTRICT v1, const T * RESTRICT v2, T * RESTRICT result)
90{
91   for ( std::size_t i = 0; i < n; i++ )
92      result[i] = v1[i] - v2[i];
93}
94
95template<typename T>
96inline void vec_scale (const std::size_t n, T * RESTRICT v, const T scalar)
97{
98   for ( std::size_t i = 0; i < n; i++ )
99      v[i] = scalar * v[i];
100}
101
102inline double vec_maxabs(const std::size_t n, const double * RESTRICT v)
103{
104   double ret = 0.0;
105   for ( std::size_t i = 0; i < n; i++ )
106      ret = std::max(ret, std::abs(v[i]));
107
108   return ret;
109}
110#if !defined(__clang__) && !defined(_MSC_VER) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 6))
111#pragma GCC diagnostic pop
112#endif
113
114#endif /* MAT_CR_H_ */
trunk/src/lib/netlist/tools/nl_convert.c
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nl_convert.c
5 *
6 */
7
8#include <algorithm>
9#include <cstdio>
10#include <cmath>
11#include "nl_convert.h"
12
13
14// for now, make buggy GCC/Mingw STFU about I64FMT
15#if (defined(__MINGW32__) && (__GNUC__ >= 5))
16#pragma GCC diagnostic push
17#pragma GCC diagnostic ignored "-Wformat"
18#pragma GCC diagnostic ignored "-Wformat-extra-args"
19#endif
20
21template<typename Class>
22static plist_t<int> bubble(const pnamedlist_t<Class *> &sl)
23{
24   plist_t<int> ret(sl.size());
25   for (unsigned i=0; i<sl.size(); i++)
26      ret[i] = i;
27
28   for(unsigned i=0; i < sl.size(); i++)
29   {
30      for(unsigned j=i+1; j < sl.size(); j++)
31      {
32         if(sl[ret[i]]->name() > sl[ret[j]]->name())
33         {
34            std::swap(ret[i], ret[j]);
35         }
36      }
37   }
38   return ret;
39}
40
41/*-------------------------------------------------
42    convert - convert a spice netlist
43-------------------------------------------------*/
44
45void nl_convert_base_t::add_pin_alias(const pstring &devname, const pstring &name, const pstring &alias)
46{
47   m_pins.add(palloc(pin_alias_t(devname + "." + name, devname + "." + alias)), false);
48}
49
50void nl_convert_base_t::add_ext_alias(const pstring &alias)
51{
52   m_ext_alias.add(alias);
53}
54
55void nl_convert_base_t::add_device(const pstring &atype, const pstring &aname, const pstring &amodel)
56{
57   m_devs.add(palloc(dev_t(atype, aname, amodel)), false);
58}
59void nl_convert_base_t::add_device(const pstring &atype, const pstring &aname, double aval)
60{
61   m_devs.add(palloc(dev_t(atype, aname, aval)), false);
62}
63void nl_convert_base_t::add_device(const pstring &atype, const pstring &aname)
64{
65   m_devs.add(palloc(dev_t(atype, aname)), false);
66}
67
68void nl_convert_base_t::add_term(pstring netname, pstring termname)
69{
70   net_t * net = m_nets.find_by_name(netname);
71   if (net == NULL)
72   {
73      net = palloc(net_t(netname));
74      m_nets.add(net, false);
75   }
76
77   /* if there is a pin alias, translate ... */
78   pin_alias_t *alias = m_pins.find_by_name(termname);
79
80   if (alias != NULL)
81      net->terminals().add(alias->alias());
82   else
83      net->terminals().add(termname);
84}
85
86void nl_convert_base_t::dump_nl()
87{
88   for (std::size_t i=0; i<m_ext_alias.size(); i++)
89   {
90      net_t *net = m_nets.find_by_name(m_ext_alias[i]);
91      // use the first terminal ...
92      out("ALIAS({}, {})\n", m_ext_alias[i].cstr(), net->terminals()[0].cstr());
93      // if the aliased net only has this one terminal connected ==> don't dump
94      if (net->terminals().size() == 1)
95         net->set_no_export();
96   }
97   plist_t<int> sorted = bubble(m_devs);
98   for (std::size_t i=0; i<m_devs.size(); i++)
99   {
100      std::size_t j = sorted[i];
101
102      if (m_devs[j]->has_value())
103         out("{}({}, {})\n", m_devs[j]->type().cstr(),
104               m_devs[j]->name().cstr(), get_nl_val(m_devs[j]->value()).cstr());
105      else if (m_devs[j]->has_model())
106         out("{}({}, \"{}\")\n", m_devs[j]->type().cstr(),
107               m_devs[j]->name().cstr(), m_devs[j]->model().cstr());
108      else
109         out("{}({})\n", m_devs[j]->type().cstr(),
110               m_devs[j]->name().cstr());
111   }
112   // print nets
113   for (std::size_t i=0; i<m_nets.size(); i++)
114   {
115      net_t * net = m_nets[i];
116      if (!net->is_no_export())
117      {
118         //printf("Net {}\n", net->name().cstr());
119         out("NET_C({}", net->terminals()[0].cstr() );
120         for (std::size_t j=1; j<net->terminals().size(); j++)
121         {
122            out(", {}", net->terminals()[j].cstr() );
123         }
124         out(")\n");
125      }
126   }
127   m_devs.clear_and_free();
128   m_nets.clear_and_free();
129   m_pins.clear_and_free();
130   m_ext_alias.clear();
131}
132
133const pstring nl_convert_base_t::get_nl_val(const double val)
134{
135   {
136      int i = 0;
137      while (m_units[i].m_unit != "-" )
138      {
139         if (m_units[i].m_mult <= std::abs(val))
140            break;
141         i++;
142      }
143      return pfmt(m_units[i].m_func.cstr())(val / m_units[i].m_mult);
144   }
145}
146double nl_convert_base_t::get_sp_unit(const pstring &unit)
147{
148   int i = 0;
149   while (m_units[i].m_unit != "-")
150   {
151      if (m_units[i].m_unit == unit)
152         return m_units[i].m_mult;
153      i++;
154   }
155   fprintf(stderr, "Unit %s unknown\n", unit.cstr());
156   return 0.0;
157}
158
159double nl_convert_base_t::get_sp_val(const pstring &sin)
160{
161   int p = sin.len() - 1;
162   while (p>=0 && (sin.substr(p,1) < "0" || sin.substr(p,1) > "9"))
163      p--;
164   pstring val = sin.substr(0,p + 1);
165   pstring unit = sin.substr(p + 1);
166
167   double ret = get_sp_unit(unit) * val.as_double();
168   return ret;
169}
170
171nl_convert_base_t::unit_t nl_convert_base_t::m_units[] = {
172      {"T",   "",      1.0e12 },
173      {"G",   "",      1.0e9  },
174      {"MEG", "RES_M({1})", 1.0e6  },
175      {"k",   "RES_K({1})", 1.0e3  }, /* eagle */
176      {"K",   "RES_K({1})", 1.0e3  },
177      {"",    "{1}",        1.0e0  },
178      {"M",   "CAP_M({1})", 1.0e-3 },
179      {"u",   "CAP_U({1})", 1.0e-6 }, /* eagle */
180      {"U",   "CAP_U({1})", 1.0e-6 },
181      {"??",   "CAP_U({1})", 1.0e-6    },
182      {"N",   "CAP_N({1})", 1.0e-9 },
183      {"P",   "CAP_P({1})", 1.0e-12},
184      {"F",   "{1}e-15",    1.0e-15},
185
186      {"MIL", "{1}",  25.4e-6},
187
188      {"-",   "{1}",  1.0  }
189};
190
191
192void nl_convert_spice_t::convert(const pstring &contents)
193{
194   pstring_list_t spnl(contents, "\n");
195
196   // Add gnd net
197
198   // FIXME: Parameter
199   out("NETLIST_START(dummy)\n");
200   add_term("0", "GND");
201
202   pstring line = "";
203
204   for (std::size_t i=0; i < spnl.size(); i++)
205   {
206      // Basic preprocessing
207      pstring inl = spnl[i].trim().ucase();
208      if (inl.startsWith("+"))
209         line = line + inl.substr(1);
210      else
211      {
212         process_line(line);
213         line = inl;
214      }
215   }
216   process_line(line);
217   dump_nl();
218   // FIXME: Parameter
219   out("NETLIST_END()\n");
220}
221
222void nl_convert_spice_t::process_line(const pstring &line)
223{
224   if (line != "")
225   {
226      pstring_list_t tt(line, " ", true);
227      double val = 0.0;
228      switch (tt[0].code_at(0))
229      {
230         case ';':
231            out("// {}\n", line.substr(1).cstr());
232            break;
233         case '*':
234            out("// {}\n", line.substr(1).cstr());
235            break;
236         case '.':
237            if (tt[0].equals(".SUBCKT"))
238            {
239               out("NETLIST_START({})\n", tt[1].cstr());
240               for (std::size_t i=2; i<tt.size(); i++)
241                  add_ext_alias(tt[i]);
242            }
243            else if (tt[0].equals(".ENDS"))
244            {
245               dump_nl();
246               out("NETLIST_END()\n");
247            }
248            else
249               out("// {}\n", line.cstr());
250            break;
251         case 'Q':
252         {
253            bool cerr = false;
254            /* check for fourth terminal ... should be numeric net
255             * including "0" or start with "N" (ltspice)
256             */
257            ATTR_UNUSED int nval =tt[4].as_long(&cerr);
258            pstring model;
259            pstring pins ="CBE";
260
261            if ((!cerr || tt[4].startsWith("N")) && tt.size() > 5)
262               model = tt[5];
263            else
264               model = tt[4];
265            pstring_list_t m(model,"{");
266            if (m.size() == 2)
267            {
268               if (m[1].len() != 4)
269                  fprintf(stderr, "error with model desc %s\n", model.cstr());
270               pins = m[1].left(3);
271            }
272            add_device("QBJT_EB", tt[0], m[0]);
273            add_term(tt[1], tt[0] + "." + pins.code_at(0));
274            add_term(tt[2], tt[0] + "." + pins.code_at(1));
275            add_term(tt[3], tt[0] + "." + pins.code_at(2));
276         }
277            break;
278         case 'R':
279            if (tt[0].startsWith("RV"))
280            {
281               val = get_sp_val(tt[4]);
282               add_device("POT", tt[0], val);
283               add_term(tt[1], tt[0] + ".1");
284               add_term(tt[2], tt[0] + ".2");
285               add_term(tt[3], tt[0] + ".3");
286            }
287            else
288            {
289               val = get_sp_val(tt[3]);
290               add_device("RES", tt[0], val);
291               add_term(tt[1], tt[0] + ".1");
292               add_term(tt[2], tt[0] + ".2");
293            }
294            break;
295         case 'C':
296            val = get_sp_val(tt[3]);
297            add_device("CAP", tt[0], val);
298            add_term(tt[1], tt[0] + ".1");
299            add_term(tt[2], tt[0] + ".2");
300            break;
301         case 'V':
302            // just simple Voltage sources ....
303            if (tt[2].equals("0"))
304            {
305               val = get_sp_val(tt[3]);
306               add_device("ANALOG_INPUT", tt[0], val);
307               add_term(tt[1], tt[0] + ".Q");
308               //add_term(tt[2], tt[0] + ".2");
309            }
310            else
311               fprintf(stderr, "Voltage Source %s not connected to GND\n", tt[0].cstr());
312            break;
313         case 'I': // Input pin special notation
314            {
315               val = get_sp_val(tt[2]);
316               add_device("ANALOG_INPUT", tt[0], val);
317               add_term(tt[1], tt[0] + ".Q");
318            }
319            break;
320         case 'D':
321            add_device("DIODE", tt[0], tt[3]);
322            /* FIXME ==> does Kicad use different notation from LTSPICE */
323            add_term(tt[1], tt[0] + ".K");
324            add_term(tt[2], tt[0] + ".A");
325            break;
326         case 'U':
327         case 'X':
328         {
329            // FIXME: specific code for KICAD exports
330            //        last element is component type
331            // FIXME: Parameter
332
333            pstring xname = tt[0].replace(".", "_");
334            pstring tname = "TTL_" + tt[tt.size()-1] + "_DIP";
335            add_device(tname, xname);
336            for (std::size_t i=1; i < tt.size() - 1; i++)
337            {
338               pstring term = pfmt("{1}.{2}")(xname)(i);
339               add_term(tt[i], term);
340            }
341            break;
342         }
343         default:
344            out("// IGNORED {}: {}\n", tt[0].cstr(), line.cstr());
345      }
346   }
347}
348
349//FIXME: should accept a stream as well
350void nl_convert_eagle_t::convert(const pstring &contents)
351{
352   pistringstream istrm(contents);
353   eagle_tokenizer tok(*this, istrm);
354
355   out("NETLIST_START(dummy)\n");
356   add_term("GND", "GND");
357   add_term("VCC", "VCC");
358   eagle_tokenizer::token_t token = tok.get_token();
359   while (true)
360   {
361      if (token.is_type(eagle_tokenizer::ENDOFFILE))
362      {
363         dump_nl();
364         // FIXME: Parameter
365         out("NETLIST_END()\n");
366         return;
367      }
368      else if (token.is(tok.m_tok_SEMICOLON))
369      {
370         /* ignore empty statements */
371         token = tok.get_token();
372      }
373      else if (token.is(tok.m_tok_ADD))
374      {
375         pstring name = tok.get_string();
376         /* skip to semicolon */
377         do
378         {
379            token = tok.get_token();
380         } while (!token.is(tok.m_tok_SEMICOLON));
381         token = tok.get_token();
382         pstring sval = "";
383         if (token.is(tok.m_tok_VALUE))
384         {
385            pstring vname = tok.get_string();
386            sval = tok.get_string();
387            tok.require_token(tok.m_tok_SEMICOLON);
388            token = tok.get_token();
389         }
390         switch (name.code_at(0))
391         {
392            case 'Q':
393            {
394               add_device("QBJT", name, sval);
395            }
396               break;
397            case 'R':
398               {
399                  double val = get_sp_val(sval);
400                  add_device("RES", name, val);
401               }
402               break;
403            case 'C':
404               {
405                  double val = get_sp_val(sval);
406                  add_device("CAP", name, val);
407               }
408               break;
409            case 'P':
410               if (sval.ucase() == "HIGH")
411                  add_device("TTL_INPUT", name, 1);
412               else if (sval.ucase() == "LOW")
413                  add_device("TTL_INPUT", name, 0);
414               else
415                  add_device("ANALOG_INPUT", name, sval.as_double());
416               add_pin_alias(name, "1", "Q");
417               break;
418            case 'D':
419               /* Pin 1 = Anode, Pin 2 = Cathode */
420               add_device("DIODE", name, sval);
421               add_pin_alias(name, "1", "A");
422               add_pin_alias(name, "2", "K");
423               break;
424            case 'U':
425            case 'X':
426            {
427               pstring tname = "TTL_" + sval + "_DIP";
428               add_device(tname, name);
429               break;
430            }
431            default:
432               tok.error("// IGNORED " + name);
433         }
434
435      }
436      else if (token.is(tok.m_tok_SIGNAL))
437      {
438         pstring netname = tok.get_string();
439         token = tok.get_token();
440         while (!token.is(tok.m_tok_SEMICOLON))
441         {
442            /* fixme: should check for string */
443            pstring devname = token.str();
444            pstring pin = tok.get_string();
445            add_term(netname, devname + "." + pin);
446            token = tok.get_token();                }
447      }
448      else
449      {
450         out("Unexpected {}\n", token.str().cstr());
451         return;
452      }
453   }
454
455}
456
457#if (defined(__MINGW32__) && (__GNUC__ >= 5))
458#pragma GCC diagnostic pop
459#endif
trunk/src/lib/netlist/tools/nl_convert.h
r0r249195
1// license:GPL-2.0+
2// copyright-holders:Couriersud
3/*
4 * nl_convert.h
5 *
6 */
7
8#pragma once
9
10#ifndef NL_CONVERT_H_
11#define NL_CONVERT_H_
12
13#include "plib/pstring.h"
14#include "plib/plists.h"
15#include "plib/pparser.h"
16
17/*-------------------------------------------------
18    convert - convert a spice netlist
19-------------------------------------------------*/
20
21class nl_convert_base_t
22{
23public:
24
25   nl_convert_base_t() : out(m_buf) {};
26   virtual ~nl_convert_base_t()
27   {
28      m_nets.clear_and_free();
29      m_devs.clear_and_free();
30      m_pins.clear_and_free();
31   }
32
33   const pstringbuffer &result() { return m_buf.str(); }
34
35   virtual void convert(const pstring &contents) = 0;
36
37protected:
38
39   void add_pin_alias(const pstring &devname, const pstring &name, const pstring &alias);
40
41   void add_ext_alias(const pstring &alias);
42
43   void add_device(const pstring &atype, const pstring &aname, const pstring &amodel);
44   void add_device(const pstring &atype, const pstring &aname, double aval);
45   void add_device(const pstring &atype, const pstring &aname);
46
47   void add_term(pstring netname, pstring termname);
48
49   void dump_nl();
50
51   const pstring get_nl_val(const double val);
52   double get_sp_unit(const pstring &unit);
53
54   double get_sp_val(const pstring &sin);
55
56   pstream_fmt_writer_t out;
57private:
58   struct net_t
59   {
60   public:
61      net_t(const pstring &aname)
62      : m_name(aname), m_no_export(false) {}
63
64      const pstring &name() { return m_name;}
65      pstring_list_t &terminals() { return m_terminals; }
66      void set_no_export() { m_no_export = true; }
67      bool is_no_export() { return m_no_export; }
68
69   private:
70      pstring m_name;
71      bool m_no_export;
72      pstring_list_t m_terminals;
73   };
74
75   struct dev_t
76   {
77   public:
78      dev_t(const pstring &atype, const pstring &aname, const pstring &amodel)
79      : m_type(atype), m_name(aname), m_model(amodel), m_val(0), m_has_val(false)
80      {}
81
82      dev_t(const pstring &atype, const pstring &aname, double aval)
83      : m_type(atype), m_name(aname), m_model(""), m_val(aval), m_has_val(true)
84      {}
85
86      dev_t(const pstring &atype, const pstring &aname)
87      : m_type(atype), m_name(aname), m_model(""), m_val(0.0), m_has_val(false)
88      {}
89
90      const pstring &name() { return m_name;}
91      const pstring &type() { return m_type;}
92      const pstring &model() { return m_model;}
93      const double &value() { return m_val;}
94
95      bool has_model() { return m_model != ""; }
96      bool has_value() { return m_has_val; }
97
98   private:
99      pstring m_type;
100      pstring m_name;
101      pstring m_model;
102      double m_val;
103      bool m_has_val;
104   };
105
106   struct unit_t {
107      pstring m_unit;
108      pstring m_func;
109      double m_mult;
110   };
111
112   struct pin_alias_t
113   {
114   public:
115      pin_alias_t(const pstring &name, const pstring &alias)
116      : m_name(name), m_alias(alias)
117      {}
118      const pstring &name() { return m_name; }
119      const pstring &alias() { return m_alias; }
120   private:
121      pstring m_name;
122      pstring m_alias;
123   };
124
125private:
126
127   postringstream m_buf;
128
129   pnamedlist_t<dev_t *> m_devs;
130   pnamedlist_t<net_t *> m_nets;
131   plist_t<pstring> m_ext_alias;
132   pnamedlist_t<pin_alias_t *> m_pins;
133
134   static unit_t m_units[];
135
136};
137
138class nl_convert_spice_t : public nl_convert_base_t
139{
140public:
141
142   nl_convert_spice_t() : nl_convert_base_t() {};
143   ~nl_convert_spice_t()
144   {
145   }
146
147   void convert(const pstring &contents);
148
149protected:
150
151   void process_line(const pstring &line);
152
153private:
154
155};
156
157class nl_convert_eagle_t : public nl_convert_base_t
158{
159public:
160
161   nl_convert_eagle_t() : nl_convert_base_t() {};
162   ~nl_convert_eagle_t()
163   {
164   }
165
166   class eagle_tokenizer : public ptokenizer
167   {
168   public:
169      eagle_tokenizer(nl_convert_eagle_t &convert, pistream &strm)
170      : ptokenizer(strm), m_convert(convert)
171      {
172         set_identifier_chars("abcdefghijklmnopqrstuvwvxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_.-");
173         set_number_chars(".0123456789", "0123456789eE-."); //FIXME: processing of numbers
174         char ws[5];
175         ws[0] = ' ';
176         ws[1] = 9;
177         ws[2] = 10;
178         ws[3] = 13;
179         ws[4] = 0;
180         set_whitespace(ws);
181         /* FIXME: gnetlist doesn't print comments */
182         set_comment("/*", "*/", "//");
183         set_string_char('\'');
184         m_tok_ADD = register_token("ADD");
185         m_tok_VALUE = register_token("VALUE");
186         m_tok_SIGNAL = register_token("SIGNAL");
187         m_tok_SEMICOLON = register_token(";");
188         /* currently not used, but required for parsing */
189         register_token(")");
190         register_token("(");
191      }
192
193      token_id_t m_tok_ADD;
194      token_id_t m_tok_VALUE;
195      token_id_t m_tok_SIGNAL;
196      token_id_t m_tok_SEMICOLON;
197
198   protected:
199
200      void verror(const pstring &msg, int line_num, const pstring &line)
201      {
202         m_convert.out("{} (line {}): {}\n", msg.cstr(), line_num, line.cstr());
203      }
204
205
206   private:
207      nl_convert_eagle_t &m_convert;
208   };
209
210   void convert(const pstring &contents);
211
212protected:
213
214
215private:
216
217};
218
219#endif /* NL_CONVERT_H_ */


Previous 199869 Revisions Next


© 1997-2024 The MAME Team