Do not generate netlist lines that use non-existent libraries.
To support that, give global scope to function inp_pathresolve() in inpcom.c. Update internal documentation (long comment).
This commit is contained in:
parent
8f8f7ff8ab
commit
5aa48cab0b
|
|
@ -169,7 +169,6 @@ static void inp_check_syntax(struct card *deck);
|
||||||
|
|
||||||
static char *inp_spawn_brace(char *s);
|
static char *inp_spawn_brace(char *s);
|
||||||
|
|
||||||
static char *inp_pathresolve(const char *name);
|
|
||||||
static char *inp_pathresolve_at(const char *name, const char *dir);
|
static char *inp_pathresolve_at(const char *name, const char *dir);
|
||||||
char *search_plain_identifier(char *str, const char *identifier);
|
char *search_plain_identifier(char *str, const char *identifier);
|
||||||
|
|
||||||
|
|
@ -1756,7 +1755,7 @@ FILE *inp_pathopen(const char *name, const char *mode)
|
||||||
if the file isn't in . and it isn't an abs path name.
|
if the file isn't in . and it isn't an abs path name.
|
||||||
*-------------------------------------------------------------------------*/
|
*-------------------------------------------------------------------------*/
|
||||||
|
|
||||||
static char *inp_pathresolve(const char *name)
|
char *inp_pathresolve(const char *name)
|
||||||
{
|
{
|
||||||
struct variable *v;
|
struct variable *v;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
|
||||||
|
|
@ -8,5 +8,5 @@
|
||||||
|
|
||||||
struct card *insert_new_line(struct card *card, char *line,
|
struct card *insert_new_line(struct card *card, char *line,
|
||||||
int linenum, int linenum_orig);
|
int linenum, int linenum_orig);
|
||||||
|
char *inp_pathresolve(const char *name);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@
|
||||||
When using XSPICE to simulate digital devices in a mixed-mode simulation,
|
When using XSPICE to simulate digital devices in a mixed-mode simulation,
|
||||||
bridging devices must be included in the circuit to pass signals between the
|
bridging devices must be included in the circuit to pass signals between the
|
||||||
analogue simulator and XSPICE. Such devices may be included in the netlist,
|
analogue simulator and XSPICE. Such devices may be included in the netlist,
|
||||||
or they may can be inserted automatically. Different types of automatic
|
or they can be inserted automatically. Different types of automatic
|
||||||
bridge may exist in the same circuit, depending on signal direction and
|
bridge may exist in the same circuit, depending on signal direction and
|
||||||
characteristics of the connected device, for example digital devices
|
characteristics of the connected device, for example digital devices
|
||||||
powered by differing voltages. Non-digital XSPICE nodes are supported.
|
powered by differing voltages. Non-digital XSPICE nodes are supported.
|
||||||
|
|
@ -95,21 +95,26 @@ for device libraries whose devices are defined by subcircuits.
|
||||||
the enclosing subcircuits for a definition of the parameter.
|
the enclosing subcircuits for a definition of the parameter.
|
||||||
If found, set vcc from the parameter.
|
If found, set vcc from the parameter.
|
||||||
|
|
||||||
3: If a command interpreter variable "no_auto_bridge_family": exists, go to
|
3: If a command interpreter variable "no_auto_bridge_family": exists,
|
||||||
step 5. Search the connected device instances for a parameter,
|
go to step 5. Search the connected XSPICE device instances for a
|
||||||
"family" with a string value. The first one found will be used.
|
parameter, "family" with a string value. The first one found will
|
||||||
If the first character of the value is not '*', the setup card will
|
be used. If no such instance exists, search for a string-valued
|
||||||
be ".include bridge_FFFFF_DDD.cir" where FFFFF is the family and
|
parameter, "family", in enclosing subcircuits, as in step 2. If
|
||||||
DDD is the signal direction for the XSPICE device: "in", "out" or
|
the first character of the value is not '*', the setup card may be
|
||||||
"inout". The device card will be "Xauto_bridge%d %s %s
|
".include bridge_FFFFF_TTTT_DDD.subcir" where FFFFF is the family,
|
||||||
bridge_FFFFF_DDD vcc=%g", so a suitably parameterised subcircuit
|
TTTT is as before and DDD is the signal direction for the XSPICE
|
||||||
must be defined in the included file.
|
device: "in", "out" or "inout". This form will be used only when
|
||||||
|
the required file can be found. In that case, the device card will
|
||||||
|
be "Xauto_bridge%d %s %s bridge_FFFFF_TTTT_DDD vcc=%g", so a
|
||||||
|
suitably parameterised subcircuit must be defined in the included
|
||||||
|
file.
|
||||||
|
|
||||||
4: If the first character of "family" was '*', look for a variable
|
4: If the first character of "family" was '*', or no file was found,
|
||||||
"auto_bridge_FFFFF_TTTT_DDD" where FFFFF is the family without '*',
|
look for a variable "auto_bridge_FFFFF_TTTT_DDD" where FFFFF is the
|
||||||
TTTT is the node type string and DDD is the direction. So this might be
|
family without '*', TTTT is the node type string and DDD is the
|
||||||
"auto_bridge_74HCT_d_inout" for a digital node. Use the variable's value
|
direction. So this might be "auto_bridge_74HCT_d_inout" for a
|
||||||
as in step 6, proceeding to step 5 if checks fail.
|
digital node. Use the variable's value as in step 6, proceeding to
|
||||||
|
step 5 if checks fail.
|
||||||
|
|
||||||
5: Look for a variable "auto_bridge_TTTT_DDD" where TTTT and DDD are as before.
|
5: Look for a variable "auto_bridge_TTTT_DDD" where TTTT and DDD are as before.
|
||||||
|
|
||||||
|
|
@ -160,9 +165,9 @@ for device libraries whose devices are defined by subcircuits.
|
||||||
|
|
||||||
and invoked by:
|
and invoked by:
|
||||||
|
|
||||||
set auto_bridge_d_out_30 = ( ".include test_sub.cir"
|
set auto_bridge_d_out = ( ".include test_sub.subcir"
|
||||||
+ "xauto_buf%d %s %s auto_buf vcc=%g"
|
+ "xauto_buf%d %s %s auto_buf vcc=%g"
|
||||||
+ 1 )
|
+ 1 )
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Working information about a type of bridge. */
|
/* Working information about a type of bridge. */
|
||||||
|
|
@ -195,10 +200,15 @@ static struct card *expand_deck(struct card *head)
|
||||||
struct card *card, *next;
|
struct card *card, *next;
|
||||||
char **pointers;
|
char **pointers;
|
||||||
int i, dico;
|
int i, dico;
|
||||||
|
bool save_debug;
|
||||||
|
|
||||||
/* Save the current parameter symbol table. */
|
/* Save the current parameter symbol table and debug global.
|
||||||
|
* Prevent overwriting of debug output in inp_readall().
|
||||||
|
*/
|
||||||
|
|
||||||
dico = nupa_add_dicoslist();
|
dico = nupa_add_dicoslist();
|
||||||
|
save_debug = ft_ngdebug;
|
||||||
|
ft_ngdebug = FALSE;
|
||||||
|
|
||||||
/* Count the cards, allocate and fill a pointer array. */
|
/* Count the cards, allocate and fill a pointer array. */
|
||||||
|
|
||||||
|
|
@ -221,6 +231,7 @@ static struct card *expand_deck(struct card *head)
|
||||||
circarray = pointers;
|
circarray = pointers;
|
||||||
card = inp_readall(NULL, Infile_Path, FALSE, TRUE, NULL);
|
card = inp_readall(NULL, Infile_Path, FALSE, TRUE, NULL);
|
||||||
card = inp_subcktexpand(card);
|
card = inp_subcktexpand(card);
|
||||||
|
ft_ngdebug = save_debug;
|
||||||
|
|
||||||
/* Destroy the parameter table that was created in subcircuit/parameter
|
/* Destroy the parameter table that was created in subcircuit/parameter
|
||||||
* expansion and restore the previous version.
|
* expansion and restore the previous version.
|
||||||
|
|
@ -479,8 +490,8 @@ static struct bridge *find_bridge(Evt_Node_Info_t *event_node,
|
||||||
family = NULL;
|
family = NULL;
|
||||||
deep = scan_devices(event_node, ckt, &family);
|
deep = scan_devices(event_node, ckt, &family);
|
||||||
|
|
||||||
/* Look for a real parameter (.param type) in the device's subcircuit
|
/* Look for a real parameter (.param type) and perhaps a string-valued
|
||||||
* and those enclosing it.
|
* "family" parameter in the device's subcircuit and those enclosing it.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
snprintf(buff, sizeof buff, "%s", deep);
|
snprintf(buff, sizeof buff, "%s", deep);
|
||||||
|
|
@ -490,7 +501,11 @@ static struct bridge *find_bridge(Evt_Node_Info_t *event_node,
|
||||||
snprintf(dot + 1, sizeof buff - (size_t)(dot - buff), "%s", vcc_parm);
|
snprintf(dot + 1, sizeof buff - (size_t)(dot - buff), "%s", vcc_parm);
|
||||||
vcc = nupa_get_param(buff, &ok);
|
vcc = nupa_get_param(buff, &ok);
|
||||||
}
|
}
|
||||||
if (ok)
|
if (!family) {
|
||||||
|
snprintf(dot + 1, sizeof buff - (size_t)(dot - buff), "family");
|
||||||
|
family = nupa_get_string_param(buff);
|
||||||
|
}
|
||||||
|
if (ok && family)
|
||||||
break;
|
break;
|
||||||
*dot = '\0';
|
*dot = '\0';
|
||||||
dot = strrchr(buff, '.');
|
dot = strrchr(buff, '.');
|
||||||
|
|
@ -506,12 +521,29 @@ static struct bridge *find_bridge(Evt_Node_Info_t *event_node,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!family)
|
||||||
|
family = nupa_get_string_param("family");
|
||||||
if (family && cp_getvar("no_auto_bridge_family", CP_BOOL, NULL, 0))
|
if (family && cp_getvar("no_auto_bridge_family", CP_BOOL, NULL, 0))
|
||||||
family = NULL;
|
family = NULL;
|
||||||
|
|
||||||
if (family && *family == '*') {
|
if (family) {
|
||||||
s_family = family + 1;
|
if (*family == '*') {
|
||||||
family = NULL; // Not used for matching.
|
s_family = family + 1; // Use variable look-up.
|
||||||
|
} else {
|
||||||
|
char *fam_inc_path;
|
||||||
|
|
||||||
|
/* Check if an include file exists for the family. */
|
||||||
|
|
||||||
|
snprintf(buff, sizeof buff, "bridge_%s_%s_%s.subcir",
|
||||||
|
family, type_name, dirs[direction]);
|
||||||
|
fam_inc_path = inp_pathresolve(buff);
|
||||||
|
if (fam_inc_path) {
|
||||||
|
tfree(fam_inc_path);
|
||||||
|
s_family = NULL;
|
||||||
|
} else {
|
||||||
|
s_family = family; // Use variable look-up.
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
s_family = NULL;
|
s_family = NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -523,10 +555,19 @@ static struct bridge *find_bridge(Evt_Node_Info_t *event_node,
|
||||||
bridge->direction == direction) {
|
bridge->direction == direction) {
|
||||||
if (family) {
|
if (family) {
|
||||||
if (!strcmp(family, bridge->family)) {
|
if (!strcmp(family, bridge->family)) {
|
||||||
/* Return vcc for formatting: requires bridge->max == 1. */
|
if (!s_family && bridge->max == 1) {
|
||||||
|
/* Set bridge vcc for formatting. */
|
||||||
|
|
||||||
bridge->vcc = vcc;
|
bridge->vcc = vcc;
|
||||||
break;
|
break;
|
||||||
|
} else {
|
||||||
|
/* Using cards from variable, or shared sub-circuit:
|
||||||
|
* vcc must also match.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (bridge->vcc == vcc)
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (bridge->vcc == vcc) { // Match vcc.
|
} else if (bridge->vcc == vcc) { // Match vcc.
|
||||||
break;
|
break;
|
||||||
|
|
@ -538,23 +579,23 @@ static struct bridge *find_bridge(Evt_Node_Info_t *event_node,
|
||||||
|
|
||||||
/* Determine if a bridging element exists, starting with the node type. */
|
/* Determine if a bridging element exists, starting with the node type. */
|
||||||
|
|
||||||
if (family) {
|
if (s_family) {
|
||||||
/* Use standard pattern for known parts family. */
|
|
||||||
|
|
||||||
snprintf(buff, sizeof buff, ".include bridge_%s_%s.cir",
|
|
||||||
family, dirs[direction]);
|
|
||||||
setup = copy(buff);
|
|
||||||
snprintf(buff, sizeof buff,
|
|
||||||
"Xauto_bridge%%d %%s %%s bridge_%s_%s vcc=%%g",
|
|
||||||
family, dirs[direction]);
|
|
||||||
format = copy(buff);
|
|
||||||
max = 1;
|
|
||||||
} else if (s_family) {
|
|
||||||
/* Family variable lookup. */
|
/* Family variable lookup. */
|
||||||
|
|
||||||
snprintf(buff, sizeof buff, "auto_bridge_%s_%s_%s",
|
snprintf(buff, sizeof buff, "auto_bridge_%s_%s_%s",
|
||||||
s_family, type_name, dirs[direction]);
|
s_family, type_name, dirs[direction]);
|
||||||
cp_getvar(buff, CP_LIST, &cvar, sizeof cvar);
|
cp_getvar(buff, CP_LIST, &cvar, sizeof cvar);
|
||||||
|
} else if (family) {
|
||||||
|
/* Use standard pattern for known parts family. */
|
||||||
|
|
||||||
|
snprintf(buff, sizeof buff, ".include bridge_%s_%s_%s.subcir",
|
||||||
|
family, type_name, dirs[direction]);
|
||||||
|
setup = copy(buff);
|
||||||
|
snprintf(buff, sizeof buff,
|
||||||
|
"Xauto_bridge%%d %%s %%s bridge_%s_%s_%s vcc=%%g",
|
||||||
|
family, type_name, dirs[direction]);
|
||||||
|
format = copy(buff);
|
||||||
|
max = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!format && !cvar) {
|
if (!format && !cvar) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue