t_vec nodes;
t_vec mosfets;
t_dict used_parts;
- t_dict io_to_node;
+ t_dict name_to_node;
} t_part;
int cmp_parts_void(const void *a_v, const void *b_v)
typedef union u_part_spec
{
char *name;
- const t_part *part;
+ t_part *part;
} t_part_spec;
int cmp_strings_void(const void *a_v, const void *b_v)
part->name = NULL;
res = ft_vec_init(&part->nodes, sizeof(t_node));
res = res || ft_vec_init(&part->mosfets, sizeof(t_mosfet));
- res = res || ft_dict_init(&part->io_to_node, sizeof(char *), sizeof(t_node *), cmp_strings_void);
+ res = res || ft_dict_init(&part->name_to_node, sizeof(char *), sizeof(t_node *), cmp_strings_void);
res = res || ft_dict_init(&part->used_parts, sizeof(char *), sizeof(t_part_spec), cmp_strings_void);
return (res != success);
}
ft_vec_free(&part->nodes, free_node);
ft_vec_free(&part->mosfets, NULL);
ft_dict_free(&part->used_parts, free_string_void, NULL);
- ft_dict_free(&part->io_to_node, free_string_void, NULL);
+ ft_dict_free(&part->name_to_node, free_string_void, NULL);
return ;
}
ft_vec_free(&part->nodes, free_node);
ft_vec_free(&part->mosfets, NULL);
ft_dict_free(&part->used_parts, free_string_void, free_string_void);
- ft_dict_free(&part->io_to_node, free_string_void, NULL);
+ ft_dict_free(&part->name_to_node, free_string_void, NULL);
return ;
}
t_mosfet *mosfet;
mosfet = node->connected.vec;
- io_node->tree = &fet->io_to_node.tree;
+ io_node->tree = &fet->name_to_node.tree;
io_node->parent = NULL;
io_node->is_black = 1;
io_node->left = NULL;
root->right = right;
right->parent = root;
left->parent = root;
- fet->io_to_node.tree.root = root;
+ fet->name_to_node.tree.root = root;
return ;
}
const int gate_drain_cmp = cmp_strings_void(&g_gate_str, &g_drain_str);
const int drain_source_cmp = cmp_strings_void(&g_drain_str, &g_source_str);
- ft_dict_init(&fet->io_to_node, sizeof(char *), sizeof(t_id), cmp_strings_void);
+ ft_dict_init(&fet->name_to_node, sizeof(char *), sizeof(t_id), cmp_strings_void);
init_fet_single_io(fet, io_node_source, ft_vec_access(&fet->nodes, 0), source);
init_fet_single_io(fet, io_node_gate, ft_vec_access(&fet->nodes, 1), gate);
init_fet_single_io(fet, io_node_drain, ft_vec_access(&fet->nodes, 2), drain);
init_fet_io(fet, io_nodes);
}
-const t_part *get_part_from_name(t_catalog *parts_catalog, const char *part_name)
+t_part *get_part_from_name(t_catalog *parts_catalog, const char *part_name)
{
static char memory_for_fets[2 * G_COMPLETE_SIZE_OF_FET_PART];
static t_part *nfet_part = NULL;
name_copy = ft_strdup(name);
if (!name_copy)
return (1);
- if (ft_dict_insert(&part->io_to_node, &name_copy, &node->id) != success)
+ if (ft_dict_insert(&part->name_to_node, &name_copy, &node->id) != success)
{
free(name_copy);
return (1);
return (0);
}
-// For simplicity the index is written in reverse order
void fill_index(char *buffer, size_t index)
{
+ size_t size;
+ const size_t index_orig = index;
+
+ size = 0;
+ while (index > 0)
+ {
+ ++size;
+ index /= 10;
+ }
+ buffer[size] = '\0';
+ --size;
+ index = index_orig;
while (index > 0)
{
- *buffer = '0' + index % 10;
+ buffer[size] = '0' + index % 10;
index /= 10;
- ++buffer;
+ --size;
}
- *buffer = '\0';
+ return ;
}
static const char g_bus_index_separator[] = "-";
return (add_io(part, ft_cget_node_child(io_list, 0)));
}
+int cmp_ids_void(const void *a_v, const void *b_v)
+{
+ const t_id *a;
+ const t_id *b;
+
+ a = a_v;
+ b = b_v;
+ return ((a > b) - (a < b));
+}
+
+t_ft_stat copy_id_void(void *dest_v, const void *src_v)
+{
+ t_id *dest;
+ const t_id *src;
+
+ dest = dest_v;
+ src = src_v;
+ *dest = *src;
+ return (success);
+}
+
+t_ft_stat copy_segment_void(void *dest_v, const void *src_v)
+{
+ t_node_segment *dest;
+ const t_node_segment *src;
+
+ dest = dest_v;
+ src = src_v;
+ *dest = *src;
+ return (success);
+}
+
+int copy_graph(t_part *main_part, t_part *used_part, t_dict *used_to_main_ids)
+{
+ const size_t original_mosfet_count = main_part->mosfets.size;
+ size_t i;
+ size_t j;
+ t_id *id;
+ t_mosfet *used_mosfet;
+ t_mosfet *new_mosfet;
+ t_node *used_node;
+ t_node *new_node;
+
+ i = 0;
+ while (i < used_part->mosfets.size)
+ {
+ used_mosfet = ft_vec_access(&used_part->mosfets, i);
+ new_mosfet = add_mosfet(&main_part->mosfets, used_mosfet->type,
+ used_mosfet->position, used_mosfet->orientation);
+ if (!new_mosfet
+ || ft_dict_insert(used_to_main_ids, &used_mosfet->id, &new_mosfet->id) != success)
+ return (1);
+ *new_mosfet = *used_mosfet;
+ new_mosfet->id = *(t_id *)ft_dict_access(used_to_main_ids, &new_mosfet->id);
+ ++i;
+ }
+ i = 0;
+ while (i < used_part->nodes.size)
+ {
+ used_node = ft_vec_access(&used_part->nodes, i);
+ new_node = add_node(&main_part->nodes, used_node->set_state);
+ if (!new_node
+ || ft_dict_insert(used_to_main_ids, &used_node->id, &new_node->id))
+ return (1);
+ *new_node = *used_node;
+ new_node->id = *(t_id *)ft_dict_access(used_to_main_ids, &new_node->id);
+ if (ft_vec_copy(&new_node->connected, &used_node->connected, copy_id_void, NULL)
+ || ft_vec_copy(&new_node->connected, &used_node->connected, copy_id_void, NULL)
+ || ft_vec_copy(&new_node->segments, &used_node->segments, copy_segment_void, NULL))
+ return (1);
+ j = 0;
+ while (j < new_node->connected.size)
+ {
+ id = ft_vec_access(&new_node->connected, j);
+ *id = *(t_id *)ft_dict_access(used_to_main_ids, &id);
+ ++j;
+ }
+ j = 0;
+ while (j < new_node->connected_gates.size)
+ {
+ id = ft_vec_access(&new_node->connected_gates, j);
+ *id = *(t_id *)ft_dict_access(used_to_main_ids, &id);
+ ++j;
+ }
+ ++i;
+ }
+ i = original_mosfet_count;
+ while (i < main_part->mosfets.size)
+ {
+ new_mosfet = ft_vec_access(&main_part->mosfets, i);
+ new_mosfet->gate = *(t_id *)ft_dict_access(used_to_main_ids, &new_mosfet->gate);
+ new_mosfet->drain = *(t_id *)ft_dict_access(used_to_main_ids, &new_mosfet->drain);
+ new_mosfet->source = *(t_id *)ft_dict_access(used_to_main_ids, &new_mosfet->source);
+ ++i;
+ }
+ return (0);
+}
+
+const char g_part_name_separator[] = ".";
+
+int record_used_io(t_part *main_part, t_part *used_part, const char *used_part_name, t_dict *used_to_main_ids)
+{
+ t_dict_traversal named_nodes;
+ t_dict_entry dict_entry;
+ size_t name_size;
+ char *name;
+ char *pin_name;
+ t_id id;
+
+ if (ft_dict_traversal_init(&named_nodes, &used_part->name_to_node) != success)
+ return (1);
+ dict_entry = ft_dict_traverse_full(&named_nodes);
+ while (dict_entry.key)
+ {
+ name = *(char **)dict_entry.key;
+ id = *(t_id *)dict_entry.el;
+ if (ft_strchr(name, *g_part_name_separator))
+ continue ;
+ name_size = ft_strlen(used_part_name) + 1 + ft_strlen(name) + 1;
+ pin_name = malloc(name_size);
+ ft_strlcpy(pin_name, used_part_name, name_size);
+ ft_strlcat(pin_name, g_part_name_separator, name_size);
+ ft_strlcat(pin_name, name, name_size);
+ id = *(t_id *)ft_dict_access(used_to_main_ids, &id);
+ if (ft_dict_insert(&main_part->name_to_node, &pin_name, &id))
+ {
+ ft_dict_traversal_free(&named_nodes);
+ return (1);
+ }
+ dict_entry = ft_dict_traverse_full(&named_nodes);
+ }
+ ft_dict_traversal_free(&named_nodes);
+ return (0);
+}
+
+int embed_part(t_part *main_part, t_part *used_part, const char *used_part_name)
+{
+ t_dict used_to_main_ids;
+
+ ft_dict_init(&used_to_main_ids, sizeof(t_id), sizeof(t_id), cmp_ids_void);
+ if (copy_graph(main_part, used_part, &used_to_main_ids))
+ {
+ ft_dict_free(&used_to_main_ids, NULL, NULL);
+ return (1);
+ }
+ if (record_used_io(main_part, used_part, used_part_name, &used_to_main_ids))
+ {
+ ft_dict_free(&used_to_main_ids, NULL, NULL);
+ return (1);
+ }
+ ft_dict_free(&used_to_main_ids, NULL, NULL);
+ return (0);
+}
+
+int build_part_graph(t_part *part);
+
+int import_subparts(t_part *part)
+{
+ t_dict_traversal used_parts_traversal;
+ t_dict_entry dict_entry;
+ char *used_part_name;
+ t_part *used_part;
+
+ if (ft_dict_traversal_init(&used_parts_traversal, &part->used_parts) != success)
+ return (1);
+ dict_entry = ft_dict_traverse_full(&used_parts_traversal);
+ while (dict_entry.key)
+ {
+ used_part_name = *(char **)dict_entry.key;
+ used_part = ((t_part_spec *)dict_entry.el)->part;
+ if (build_part_graph(used_part) || embed_part(part, used_part, used_part_name))
+ {
+ ft_dict_traversal_free(&used_parts_traversal);
+ return (1);
+ }
+ dict_entry = ft_dict_traverse_full(&used_parts_traversal);
+ }
+ return (0);
+}
+
+int is_state_setting_connection(const t_parse_tree_node *connection)
+{
+ return (!ft_strcmp(ft_cget_node_child(connection, 0)->token.type, g_defined_tokens[node_state].type)
+ || !ft_strcmp(ft_cget_node_child(connection, 2)->token.type, g_defined_tokens[node_state].type));
+}
+
+int is_pin_pin_connection(const t_parse_tree_node *connection)
+{
+ return (!is_state_setting_connection(connection)
+ && !ft_strcmp(ft_cget_node_child(connection, 1)->token.type, g_defined_tokens[hyphen].type));
+}
+
+int is_bus_bus_connection(const t_parse_tree_node *connection)
+{
+ return (!is_state_setting_connection(connection)
+ && !ft_strcmp(ft_cget_node_child(connection, 1)->token.type, g_defined_tokens[equal_sign].type));
+}
+
+t_state parsed_node_to_state(const t_parse_tree_node *state_node)
+{
+ t_state state;
+
+ state = 0;
+ while (state < state_count)
+ {
+ if (!ft_strcmp(state_node->token.str, g_node_state_strings[state]))
+ return (state);
+ ++state;
+ }
+ return (unknown);
+}
+
+char *get_pin_name(const t_parse_tree_node *pin_spec)
+{
+ const char *part_name;
+ const char *pin_name;
+ const char *index;
+ char *whole_name;
+ const t_parse_tree_node *helper_node;
+
+ if (pin_spec->children.size == 1)
+ {
+ part_name = NULL;
+ helper_node = ft_cget_node_child(pin_spec, 0);
+ }
+ else
+ {
+ part_name = ft_cget_child_deep(pin_spec, 0, 0, 0)->token.str;
+ helper_node = ft_cget_node_child(pin_spec, 2);
+ }
+ pin_name = ft_cget_child_deep(helper_node, 0, 0, 0)->token.str;
+ if (helper_node->children.size == 1)
+ index = NULL;
+ else
+ index = ft_cget_child_deep(helper_node, 1, 1, 0)->token.str;
+ size = ft_strlen(part_name) + (part_name != NULL) * g_part_name_separator
+ + ft_strlen(pin_name) + (index != NULL) * g_bus_index_separator + ft_strlen(index) + 1;
+ whole_name = malloc(size);
+ whole_name[0] = '\0';
+ if (part_name)
+ {
+ ft_strlcat(whole_name, part_name, size);
+ ft_strlcat(whole_name, g_part_name_separator, size);
+ }
+ ft_strlcat(whole_name, pin_name, size);
+ if (index)
+ {
+ ft_strlcat(whole_name, g_bus_index_separator, size);
+ ft_strlcat(whole_name, index, size);
+ }
+ return (whole_name);
+}
+
+int set_pin_state(t_part *part, const t_parse_tree_node *pin_spec, t_state state)
+{
+ char *name;
+ t_id id;
+
+ name = get_pin_name(pin_spec);
+ if (!name)
+ return (1);
+ id = *(t_id *)ft_dict_access(&part->name_to_node, name);
+ free(name);
+ get_node_by_id(&part->nodes, id)->set_state = state;
+ return (0);
+}
+
+int set_bus_state(t_part *part, const t_parse_tree_node *bus_spec, t_state state)
+{
+ char *name;
+ t_id id;
+ size_t i;
+ size_t last_index;
+ size_t index_offset;
+ const t_parse_tree_node *helper;
+
+ index_offset = get_and_prefill_buffer(&name, part, bus_spec);
+ helper = ft_cget_node_child(bus_spec, bus_spec->children.size - 1);
+ if (helper->children.size == 1)
+ {
+ i = 1;
+ last_index =
+}
+
+int set_state_from_connection(t_part *part, const t_parse_tree_node *connection)
+{
+ t_state state;
+ const t_parse_tree_node *state_node;
+ const t_parse_tree_node *helper_node;
+ t_id id;
+
+ helper_node = ft_cget_node_child(connection, 0);
+ if (!ft_strcmp(helper_node->token.type, g_defined_tokens[node_state].type))
+ {
+ state_node = helper_node;
+ helper_node = ft_cget_node_child(connection, 2);
+ }
+ else
+ state_node = ft_cget_node_child(connection, 2);
+ state = parsed_node_to_state(state_node);
+ if (!ft_strcmp(helper_node->token.type, "PinSpec"))
+ return (set_pin_state(part, helper_node, state));
+ if (!ft_strcmp(ft_cget_node_child(connection, 1)->token.type, g_defined_tokens[equal_sign].type))
+ return (set_bus_state(part, helper_node, state));
+ id = tie_bus(part, helper_node);
+ if (id == INVALID_ID)
+ return (1);
+ get_node_by_id(&part->nodes, id)->set_state = state;
+ return (0);
+}
+
+int add_connection(t_part *part, const t_parse_tree_node *connection)
+{
+ if (is_state_setting_connection(connection))
+ return (set_state_from_connection(part, connection));
+ if (is_pin_pin_connection(connection))
+ return (add_pin_pin_connection(part, connection));
+ if (is_bus_bus_connection(connection))
+ return (add_bus_bus_connection(part, connection));
+ return (add_pin_bus_connection(part, connection));
+}
+
+int realise_connections(t_part *part)
+{
+ const t_parse_tree_node *connection_list;
+
+ connection_list = ft_cget_child_deep(part->parsed_node, 2, 3, 1);
+ while (connection_list->children.size == 3)
+ {
+ if (add_connection(part, ft_cget_node_child(connection_list, 2)))
+ return (1);
+ connection_list = ft_cget_node_child(connection_list, 0);
+ }
+ return (add_connection(part, ft_cget_node_child(connection_list, 0)));
+}
+
int build_part_graph(t_part *part)
{
+ if (part->is_graph_built == 1)
+ return (0);
if (prepare_io(part))
return (1);
+ if (import_subparts(part))
+ return (1);
+ if (realise_connections(part))
+ return (1);
+ part->is_graph_built = 1;
return (0);
}