From: Lukáš Jiřiště Date: Sat, 20 Sep 2025 20:04:38 +0000 (+0200) Subject: Finish parsing of files X-Git-Url: https://git.ljiriste.work/?a=commitdiff_plain;h=91cc1f8892196da1c094bb8258aabbe4ad4e7997;p=FET_sim.git Finish parsing of files The load instruction now is able to go through the file and properly parse it into a graph. It mostly fails silently for now. It also just deletes the graph as soon as it is constructed, because the transfer is not yet implemented (but should be easy). Some additional fixes were done, now valgrind does not report any leak (except for ncurses). A sample test was also added which should feature most of the current capabilities. It does not test subbus access so far. --- diff --git a/Libft b/Libft index 7ea0e5e..30f8df1 160000 --- a/Libft +++ b/Libft @@ -1 +1 @@ -Subproject commit 7ea0e5eab36b56b286a76770d618ff5ea5fc3be7 +Subproject commit 30f8df1bfda39333988817e9f5312e71905dbc34 diff --git a/TODO b/TODO index 67bf114..f6f5997 100644 --- a/TODO +++ b/TODO @@ -4,8 +4,8 @@ fix file not loading when load command repeated with empty command make build_graph not output rewrite command parsing (what I've created is just ugly) come up with better file structure -create language to write circuits in (circuit language?) (something like MHRD language?) implement circuit builder that converts circuit language to FET_sim representation in order to simulate + - mostly done Group nodes and mosfets in a "graph" structure add even more simulation commands(eg. delete node/fet) test the project diff --git a/samples/test b/samples/test new file mode 100644 index 0000000..36ed76a --- /dev/null +++ b/samples/test @@ -0,0 +1,509 @@ +not; + connectors: + in, + out; + parts: + n - n, + p - p; + connections: + n.source - p.drain, + n.gate - p.gate, + p.source - on, + n.drain - off, + in - n.gate, + out - n.source; + +nmos_nand; + connectors: + a, + b, + out, + source; + parts: + na - n, + nb - n; + connections: + a - na.gate, + b - nb.gate, + na.source - out, + na.drain - nb.source, + nb.drain - source, + source - off, + out - pull_up; + +pmos_nor; + connectors: + a, + b, + out, + source; + parts: + pa - p, + pb - p; + connections: + a - pa.gate, + b - pb.gate, + pa.source - source, + pa.drain - pb.source, + pb.drain - out, + source - on, + out - pull_down; + +nmos_nor; + connectors: + a, + b, + out, + source; + parts: + na - n, + nb - n; + connections: + a - na.gate, + b - nb.gate, + na.source - nb.source, + na.source - out, + na.drain - nb.drain, + na.drain - source, + source - off, + out - pull_up; + +pmos_nand; + connectors: + a, + b, + out, + source; + parts: + pa - p, + pb - p; + connections: + a - pa.gate, + b - pb.gate, + pa.source - pb.source, + pa.source - source, + pa.drain - pb.drain, + pa.drain - out, + source - on, + out - pull_down; + +nand; + connectors: + a, + b, + out; + parts: + p_nand - pmos_nand, + n_nand - nmos_nand; + connections: + a - p_nand.a, + a - n_nand.a, + b - p_nand.b, + b - n_nand.b, + out - p_nand.out, + out - n_nand.out, + out - floating; + +nor; + connectors: + a, + b, + out; + parts: + p_nor - pmos_nor, + n_nor - nmos_nor; + connections: + a - p_nor.a, + a - n_nor.a, + b - p_nor.b, + b - n_nor.b, + out - p_nor.out, + out - n_nor.out, + out - floating; + +and; + connectors: + a, + b, + out; + parts: + not - not, + nand - nand; + connections: + a - nand.a, + b - nand.b, + nand.out - not.in, + not.out - out; + +or; + connectors: + a, + b, + out; + parts: + not - not, + nor - nor; + connections: + a - nor.a, + b - nor.b, + nor.out - not.in, + not.out - out; + +xor; + connectors: + a, + b, + out; + parts: + nota - not, + notb - not, + nand1 - pmos_nand, + nand2 - pmos_nand, + nor1 - nmos_nor, + nor2 - nmos_nor; + connections: + a - nota.in, + b - notb.in, + a - nand1.a, + b - nand1.b, + nota.out - nand2.a, + notb.out - nand2.b, + nand1.out - nand2.source, + nand2.source - floating, + a - nor1.a, + notb.out - nor1.b, + nota.out - nor2.a, + b - nor2.b, + nor1.out - nor2.source, + nor2.source - floating, + nor2.out - out, + nand2.out - out, + out - floating; + +not4; + connectors: + in[4], + out[4]; + parts: + n0 - not, + n1 - not, + n2 - not, + n3 - not; + connections: + in[0] - n0.in, + in[1] - n1.in, + in[2] - n2.in, + in[3] - n3.in, + n0.out - out[0], + n1.out - out[1], + n2.out - out[2], + n3.out - out[3]; + +nand4; + connectors: + a[4], + b[4], + out[4]; + parts: + nand0 - nand, + nand1 - nand, + nand2 - nand, + nand3 - nand; + connections: + a[0] - nand0.a, + b[0] - nand0.b, + a[1] - nand1.a, + b[1] - nand1.b, + a[2] - nand2.a, + b[2] - nand2.b, + a[3] - nand3.a, + b[3] - nand3.b, + nand0.out - out[0], + nand1.out - out[1], + nand2.out - out[2], + nand3.out - out[3]; + +nor4; + connectors: + a[4], + b[4], + out[4]; + parts: + nor0 - nor, + nor1 - nor, + nor2 - nor, + nor3 - nor; + connections: + a[0] - nor0.a, + b[0] - nor0.b, + a[1] - nor1.a, + b[1] - nor1.b, + a[2] - nor2.a, + b[2] - nor2.b, + a[3] - nor3.a, + b[3] - nor3.b, + nor0.out - out[0], + nor1.out - out[1], + nor2.out - out[2], + nor3.out - out[3]; + +and4; + connectors: + a[4], + b[4], + out[4]; + parts: + not - not4, + nand - nand4; + connections: + a = nand.a, + b = nand.b, + nand.out = not.out, + not.out = out; + +or4; + connectors: + a[4], + b[4], + out[4]; + parts: + not - not4, + nor - nor4; + connections: + a = nor.a, + b = nor.b, + nor.out = not.out, + not.out = out; + +xor4; + connectors: + a[4], + b[4], + out[4]; + parts: + xor0 - xor, + xor1 - xor, + xor2 - xor, + xor3 - xor; + connections: + a[0] - xor0.a, + b[0] - xor0.b, + a[1] - xor1.a, + b[1] - xor1.b, + a[2] - xor2.a, + b[2] - xor2.b, + a[3] - xor3.a, + b[3] - xor3.b, + xor0.out - out[0], + xor1.out - out[1], + xor2.out - out[2], + xor3.out - out[3]; + +adder; + connectors: + carry_in, + a, + b, + out, + carry_out; + parts: + xor_main - xor, + xor_carry - xor, + and_main - and, + and_carry - and, + or_carry - or; + connections: + a - xor_main.a, + b - xor_main.b, + a - and_main.a, + b - and_main.b, + xor_main.out - xor_carry.a, + carry_in - xor_carry.b, + xor_main.out - and_carry.a, + carry_in - and_carry.b, + xor_carry.out - out, + and_main.out - or_carry.a, + and_carry.out - or_carry.b, + or_carry.out - carry_out; + +adder4; + connectors: + carry_in, + a[4], + b[4], + out[4], + carry_out; + parts: + add0 - adder, + add1 - adder, + add2 - adder, + add3 - adder; + connections: + carry_in - add0.carry_in, + add0.carry_out - add1.carry_in, + add1.carry_out - add2.carry_in, + add2.carry_out - add3.carry_in, + add3.carry_out - carry_out, + a[0] - add0.a, + b[0] - add0.b, + out[0] - add0.out, + a[1] - add1.a, + b[1] - add1.b, + out[1] - add1.out, + a[2] - add2.a, + b[2] - add2.b, + out[2] - add2.out, + a[3] - add3.a, + b[3] - add3.b, + out[3] - add3.out; + + +mux; + connectors: + a, + b, + sel, + out; + parts: + p_nand_a - pmos_nand, + p_nand_b - pmos_nand, + n_nand_a - nmos_nand, + n_nand_b - nmos_nand, + not_sel - not, + not_not_out - not; + connections: + sel - p_nand_a.a, + a - p_nand_a.b, + sel - not_sel.in, + not_sel.out - p_nand_b.a, + b - p_nand_b.b, + not_not_out.out - out, + p_nand_a.out - not_not_out.in, + p_nand_b.out - not_not_out.in, + n_nand_a.out - not_not_out.in, + not_not_out.in - floating, + n_nand_a.a - a, + n_nand_a.b - not_sel.out, + n_nand_a.source - n_nand_b.out, + n_nand_b.out - floating, + n_nand_b.a - sel, + n_nand_b.b - b; + +mux1x2; + connectors: + a, + b, + sel, + out; + parts: + mux - mux; + connections: + a - mux.a, + b - mux.b, + sel - mux.sel, + out - mux.out; + +mux1x4; + connectors: + a, + b, + c, + d, + sel[2], + out; + parts: + mux_ab - mux1x2, + mux_cd - mux1x2, + mux_out - mux1x2; + connections: + a - mux_ab.a, + b - mux_ab.b, + c - mux_cd.a, + d - mux_cd.b, + sel[0] - mux_ab.sel, + sel[0] - mux_cd.sel, + mux_ab.out - mux_out.a, + mux_cd.out - mux_out.b, + sel[1] - mux_out.sel, + mux_out.out - out; + +mux4x2; + connectors: + a[4], + b[4], + sel, + out[4]; + parts: + mux0 - mux, + mux1 - mux, + mux2 - mux, + mux3 - mux; + connections: + a[0] - mux0.a, + b[0] - mux0.b, + sel - mux0.sel, + mux0.out - out[0], + a[1] - mux1.a, + b[1] - mux1.b, + sel - mux1.sel, + mux1.out - out[1], + a[2] - mux2.a, + b[2] - mux2.b, + sel - mux2.sel, + mux2.out - out[2], + a[3] - mux3.a, + b[3] - mux3.b, + sel - mux3.sel, + mux3.out - out[3]; + +mux4x4; + connectors: + a[4], + b[4], + c[4], + d[4], + sel[2], + out[4]; + parts: + mux_ab - mux4x2, + mux_cd - mux4x2, + mux_out - mux4x2; + connections: + a = mux_ab.a, + b = mux_ab.b, + c = mux_cd.a, + d = mux_cd.b, + sel[0] - mux_ab.sel, + sel[0] - mux_cd.sel, + mux_ab.out = mux_out.a, + mux_cd.out = mux_out.b, + sel[1] - mux_out.sel, + mux_out.out = out; +main; + connectors: + a[4], + b[4], + op[2], + out[4]; + parts: + nand - nand4, + nor - nor4, + xor - xor4, + adder - adder4, + mux - mux4x4; + connections: + a = nand.a, + b = nand.b, + a = nor.a, + b = nor.b, + a = xor.a, + b = xor.b, + a = adder.a, + b = adder.b, + off - adder.carry_in, + nand.out = mux.a, + nor.out = mux.b, + xor.out = mux.c, + adder.out = mux.d, + op = mux.sel, + mux.out = out; diff --git a/src/c_load.c b/src/c_load.c index a1488d8..64142e8 100644 --- a/src/c_load.c +++ b/src/c_load.c @@ -126,7 +126,7 @@ char *string_to_type(const char *str) while (state < state_count) { if (!ft_strcmp(str, g_node_state_strings[state])) - return (ft_strdup(g_defined_tokens[state].type)); + return (ft_strdup(g_defined_tokens[node_state].type)); ++state; } return (ft_strdup(g_defined_tokens[string].type)); @@ -195,6 +195,7 @@ int tokenize(t_vec *tokens, int fd) else { free(line); + free_token(&info_token); ft_vec_free(tokens, free_token_void); return (1); } @@ -211,7 +212,10 @@ int tokenize(t_vec *tokens, int fd) free(tmp); tmp = get_next_line(fd); if (!tmp) + { + free(line); break; + } ft_strcat_alloc(&line, tmp); free(tmp); } @@ -255,6 +259,18 @@ int cmp_strings_void(const void *a_v, const void *b_v) return (ft_strcmp(*a, *b)); } +typedef union u_raw_pinbus +{ + t_id pin; + t_vec bus; +} t_raw_pinbus; + +typedef struct s_pinbus +{ + int is_pin; + t_raw_pinbus pinbus; +} t_pinbus; + int init_new_part(t_part *part) { t_ft_stat res; @@ -262,7 +278,7 @@ int init_new_part(t_part *part) 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->name_to_node, sizeof(char *), sizeof(t_node *), cmp_strings_void); + res = res || ft_dict_init(&part->name_to_node, sizeof(char *), sizeof(t_pinbus), cmp_strings_void); res = res || ft_dict_init(&part->used_parts, sizeof(char *), sizeof(t_part_spec), cmp_strings_void); return (res != success); } @@ -276,6 +292,17 @@ void free_string_void(void *string_v) return ; } +void free_pinbus_void(void *pinbus_v) +{ + t_pinbus *pinbus; + + pinbus = pinbus_v; + if (pinbus->is_pin) + return ; + ft_vec_free(&pinbus->pinbus.bus, NULL); + return ; +} + void free_part(t_part *part) { if (!part) @@ -284,7 +311,7 @@ void free_part(t_part *part) 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->name_to_node, free_string_void, NULL); + ft_dict_free(&part->name_to_node, free_string_void, free_pinbus_void); return ; } @@ -302,7 +329,7 @@ void free_part_with_used_names(t_part *part) 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->name_to_node, free_string_void, NULL); + ft_dict_free(&part->name_to_node, free_string_void, free_pinbus_void); return ; } @@ -365,6 +392,7 @@ int extract_used_names(t_catalog *part_catalog, t_parse_tree_node *part_spec_lis if (!new_part.name) return (1); used_parts = ft_cget_child_deep(new_part.parsed_node, 2, 2, 1); + res = 0; while (used_parts->children.size == 3) { res = write_used_part(&new_part, ft_cget_node_child(used_parts, 2)); @@ -414,7 +442,7 @@ static const char g_p_name[] = "p"; static const char g_n_name[] = "n"; // IO needs to hold node id instead of pointer -#define G_SIZE_OF_IO_NODE (sizeof(t_rbtree_node) + sizeof(char *) + sizeof(t_id)) +#define G_SIZE_OF_IO_NODE (sizeof(t_rbtree_node) + sizeof(char *) + sizeof(t_pinbus)) #define G_COMPLETE_SIZE_OF_FET_PART (sizeof(t_part) + 3 * (sizeof(t_node)) + sizeof(t_id) + sizeof(t_mosfet) + 3 * G_SIZE_OF_IO_NODE) void init_fet_nodes(t_part *fet, t_node *nodes, t_id *mosfet) @@ -455,14 +483,17 @@ void init_fet_mosfet(t_part *fet, t_mosfet *mosfet, t_type type) void init_fet_single_io(t_part *fet, t_rbtree_node *io_node, t_node *node, t_terminal terminal) { t_mosfet *mosfet; + t_pinbus pinbus; - mosfet = node->connected.vec; + pinbus.is_pin = 1; + pinbus.pinbus.pin = node->id; + mosfet = ft_vec_access(&fet->mosfets, 0); io_node->tree = &fet->name_to_node.tree; io_node->parent = NULL; io_node->is_black = 1; io_node->left = NULL; io_node->right = NULL; - ft_memcpy((char *)&io_node->data + sizeof(char *), &node->id, sizeof(t_id)); + ft_memcpy((char *)&io_node->data + sizeof(char *), &pinbus, sizeof(t_pinbus)); if (terminal == source) { bind_fet_node(&fet->nodes, mosfet, node, source); @@ -498,7 +529,7 @@ void init_fet_io(t_part *fet, t_rbtree_node *io_node_source) 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->name_to_node, sizeof(char *), sizeof(t_id), cmp_strings_void); + ft_dict_init(&fet->name_to_node, sizeof(char *), sizeof(t_pinbus), 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); @@ -527,6 +558,8 @@ void initialize_fet_part(t_part *fet, t_type type) init_fet_nodes(fet, nodes, mosfet_id); init_fet_mosfet(fet, mosfet, type); init_fet_io(fet, io_nodes); + fet->is_graph_built = 1; + return ; } t_part *get_part_from_name(t_catalog *parts_catalog, const char *part_name) @@ -593,8 +626,9 @@ int rebind_names_to_parts(t_catalog *parts_catalog) int add_pin(t_part *part, const char *name) { - t_node *node; - char *name_copy; + t_node *node; + char *name_copy; + t_pinbus pin; node = add_node(&part->nodes, floating); if (!node) @@ -602,7 +636,9 @@ int add_pin(t_part *part, const char *name) name_copy = ft_strdup(name); if (!name_copy) return (1); - if (ft_dict_insert(&part->name_to_node, &name_copy, &node->id) != success) + pin.is_pin = 1; + pin.pinbus.pin = node->id; + if (ft_dict_insert(&part->name_to_node, &name_copy, &pin) != success) { free(name_copy); return (1); @@ -610,64 +646,47 @@ int add_pin(t_part *part, const char *name) return (0); } -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[size] = '0' + index % 10; - index /= 10; - --size; - } - return ; -} - -static const char g_bus_index_separator[] = "-"; - int add_bus(t_part *part, const t_parse_tree_node *bus_spec) { - const char *const bus_name = ft_cget_child_deep(bus_spec, 3, 0, 0, 0)->token.str; const char *const bus_size_str = ft_cget_child_deep(bus_spec, 2, 2, 0)->token.str; + char *name; size_t bus_size; - char *buffer; - size_t buffer_size; - size_t base_size; + t_pinbus bus; + t_node *node; bus_size = (size_t)ft_atoi(bus_size_str); - buffer = ft_itoa((int)bus_size); - if (!buffer || ft_strcmp(buffer, bus_size_str)) + name = ft_itoa((int)bus_size); + if (!name || ft_strcmp(name, bus_size_str)) { - free(buffer); + free(name); return (1); } - free(buffer); - base_size = ft_strlen(bus_name) + ft_strlen(g_bus_index_separator); - buffer_size = base_size + ft_strlen(bus_size_str) + 1; - buffer = malloc(buffer_size); - if (!buffer) + free(name); + ft_vec_init(&bus.pinbus.bus, sizeof(t_id)); + if (ft_vec_reserve(&bus.pinbus.bus, bus_size) != success) return (1); + bus.is_pin = 0; while (bus_size > 0) { - --bus_size; - ft_strlcpy(buffer, bus_name, buffer_size); - ft_strlcat(buffer, g_bus_index_separator, buffer_size); - fill_index(buffer + base_size, bus_size); - if (add_pin(part, buffer)) + node = add_node(&part->nodes, floating); + if (!node || ft_vec_append(&bus.pinbus.bus, &node->id) != success) { - free(buffer); + ft_vec_free(&bus.pinbus.bus, NULL); return (1); } + --bus_size; + } + name = ft_strdup(ft_cget_child_deep(bus_spec, 3, 0, 0, 0)->token.str); + if (!name) + { + ft_vec_free(&bus.pinbus.bus, NULL); + return (1); + } + if (ft_dict_insert(&part->name_to_node, &name, &bus) != success) + { + ft_vec_free(&bus.pinbus.bus, NULL); + free(name); + return (1); } return (0); } @@ -700,7 +719,7 @@ int cmp_ids_void(const void *a_v, const void *b_v) a = a_v; b = b_v; - return ((a > b) - (a < b)); + return ((*a > *b) - (*a < *b)); } t_ft_stat copy_id_void(void *dest_v, const void *src_v) @@ -760,21 +779,21 @@ int copy_graph(t_part *main_part, t_part *used_part, t_dict *used_to_main_ids) *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->connected_gates, &used_node->connected_gates, 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); + *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); + *id = *(t_id *)ft_dict_access(used_to_main_ids, id); ++j; } ++i; @@ -799,8 +818,10 @@ int record_used_io(t_part *main_part, t_part *used_part, const char *used_part_n t_dict_entry dict_entry; size_t name_size; char *name; - char *pin_name; - t_id id; + char *pinbus_name; + size_t i; + t_pinbus pinbus; + t_id *id; if (ft_dict_traversal_init(&named_nodes, &used_part->name_to_node) != success) return (1); @@ -808,16 +829,36 @@ int record_used_io(t_part *main_part, t_part *used_part, const char *used_part_n while (dict_entry.key) { name = *(char **)dict_entry.key; - id = *(t_id *)dict_entry.el; + pinbus = *(t_pinbus *)dict_entry.el; if (ft_strchr(name, *g_part_name_separator)) + { + dict_entry = ft_dict_traverse_full(&named_nodes); 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)) + pinbus_name = malloc(name_size); + ft_strlcpy(pinbus_name, used_part_name, name_size); + ft_strlcat(pinbus_name, g_part_name_separator, name_size); + ft_strlcat(pinbus_name, name, name_size); + if (pinbus.is_pin) + pinbus.pinbus.pin = *(t_id *)ft_dict_access(used_to_main_ids, &pinbus.pinbus.pin); + else + { + if (ft_vec_copy(&pinbus.pinbus.bus, &((t_pinbus *)dict_entry.el)->pinbus.bus, + copy_id_void, NULL) != success) + { + ft_dict_traversal_free(&named_nodes); + return (1); + } + i = 0; + while (i < pinbus.pinbus.bus.size) + { + id = ft_vec_access(&pinbus.pinbus.bus, i); + *id = *(t_id *)ft_dict_access(used_to_main_ids, id); + ++i; + } + } + if (ft_dict_insert(&main_part->name_to_node, &pinbus_name, &pinbus)) { ft_dict_traversal_free(&named_nodes); return (1); @@ -905,76 +946,199 @@ t_state parsed_node_to_state(const t_parse_tree_node *state_node) return (unknown); } -char *get_pin_name(const t_parse_tree_node *pin_spec) +char *get_pinbus_name(const t_parse_tree_node *pinbus_spec) { + size_t size; const char *part_name; - const char *pin_name; - const char *index; + const char *pinbus_name; char *whole_name; const t_parse_tree_node *helper_node; - if (pin_spec->children.size == 1) + if (pinbus_spec->children.size == 1) { part_name = NULL; - helper_node = ft_cget_node_child(pin_spec, 0); + helper_node = ft_cget_node_child(pinbus_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); + part_name = ft_cget_child_deep(pinbus_spec, 3, 0, 0, 0)->token.str; + helper_node = ft_cget_node_child(pinbus_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; + pinbus_name = ft_cget_child_deep(helper_node, 3, 0, 0, 0)->token.str; + size = ft_strlen(part_name) + (part_name != NULL) * ft_strlen(g_part_name_separator) + + ft_strlen(pinbus_name) + 1; whole_name = malloc(size); + if (!whole_name) + return (NULL); 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); - } + ft_strlcat(whole_name, pinbus_name, size); return (whole_name); } -int set_pin_state(t_part *part, const t_parse_tree_node *pin_spec, t_state state) +t_pinbus *get_pinbus_from_spec(t_part *part, const t_parse_tree_node *pinbus_spec) { - char *name; - t_id id; + char *name; + t_pinbus *pinbus; - name = get_pin_name(pin_spec); + name = get_pinbus_name(pinbus_spec); if (!name) - return (1); - id = *(t_id *)ft_dict_access(&part->name_to_node, name); + return (NULL); + pinbus = ft_dict_access(&part->name_to_node, &name); free(name); + return (pinbus); +} + +int set_pin_state(t_part *part, const t_parse_tree_node *pin_spec, t_state state) +{ + size_t index; + const t_pinbus *pinbus; + t_id id; + + pinbus = get_pinbus_from_spec(part, pin_spec); + if (!pinbus) + return (1); + if (pinbus->is_pin) + id = pinbus->pinbus.pin; + else + { + index = (size_t)ft_atoi(ft_cget_child_deep(pin_spec, 3, (int)pin_spec->children.size - 1, 1, 1)->token.str); + if (index >= pinbus->pinbus.bus.size) + return (1); + id = *(const t_id *)ft_vec_caccess(&pinbus->pinbus.bus, index); + } get_node_by_id(&part->nodes, id)->set_state = state; return (0); } +int get_subbus_indeces(const t_pinbus *pinbus, const t_parse_tree_node *bus_pinbus_spec, size_t *first, size_t *last) +{ + const t_parse_tree_node *part_bus_pinbus_spec; + + part_bus_pinbus_spec = ft_cget_node_child(bus_pinbus_spec, bus_pinbus_spec->children.size - 1); + if (part_bus_pinbus_spec->children.size == 1) + { + *first = 0; + if (!last) + return (1); + *last = pinbus->pinbus.bus.size - 1; + } + else + { + *first = (size_t)ft_atoi(ft_cget_child_deep(part_bus_pinbus_spec, 3, 1, 1, 0)->token.str); + if (*first >= pinbus->pinbus.bus.size) + return (1); + if (last) + { + *last = (size_t)ft_atoi(ft_cget_child_deep(part_bus_pinbus_spec, 3, 1, 3, 0)->token.str); + if (*last >= pinbus->pinbus.bus.size) + return (1); + } + } + return (0); +} + +void swap_indeces(size_t *a, size_t *b) +{ + size_t tmp; + + tmp = *a; + *a = *b; + *b = tmp; + return ; +} + 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; + const t_pinbus *pinbus; - 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) + pinbus = get_pinbus_from_spec(part, bus_spec); + if (!pinbus + || get_subbus_indeces(pinbus, bus_spec, &i, &last_index)) + return (1); + if (i > last_index) + swap_indeces(&i, &last_index); + while (i <= last_index) + { + get_node_by_id(&part->nodes, + *(const t_id *)ft_vec_caccess(&pinbus->pinbus.bus, i++)) + ->set_state = state; + } + return (0); +} + +void remap_bus_ids(t_vec *bus, t_id to, t_id from) +{ + size_t i; + t_id *id; + + i = 0; + while (i < bus->size) + { + id = ft_vec_access(bus, i); + if (*id == from) + *id = to; + ++i; + } + return ; +} + +// to was chosen before from so that the IDs can be given in the same order as merging nodes +int remap_ids(t_part *part, t_id to, t_id from) +{ + t_dict_traversal traversal; + t_pinbus *pinbus; + + if (ft_dict_traversal_init(&traversal, &part->name_to_node) != success) + return (1); + pinbus = ft_dict_traverse(&traversal); + while (pinbus) + { + if (pinbus->is_pin && pinbus->pinbus.pin == from) + pinbus->pinbus.pin = to; + else if (!pinbus->is_pin) + remap_bus_ids(&pinbus->pinbus.bus, to, from); + pinbus = ft_dict_traverse(&traversal); + } + ft_dict_traversal_free(&traversal); + return (0); +} + +t_node *tie_bus(t_part *part, const t_parse_tree_node *bus_spec) +{ + size_t i; + size_t last_index; + t_id id; + t_pinbus *pinbus; + t_node *base_node; + t_node *merged_node; + + pinbus = get_pinbus_from_spec(part, bus_spec); + if (!pinbus + || get_subbus_indeces(pinbus, bus_spec, &i, &last_index)) + return (NULL); + if (i > last_index) + { + i += last_index; + last_index = i - last_index; + i -= last_index; + } + base_node = get_node_by_id(&part->nodes, *(const t_id *)ft_vec_caccess(&pinbus->pinbus.bus, i++)); + while (i <= last_index) { - i = 1; - last_index = + id = *(t_id *)ft_vec_access(&pinbus->pinbus.bus, i++); + merged_node = get_node_by_id(&part->nodes, id); + if (merge_nodes(&part->nodes, &part->mosfets, base_node, merged_node)) + return (NULL); + remap_ids(part, base_node->id, id); + } + return (base_node); } int set_state_from_connection(t_part *part, const t_parse_tree_node *connection) @@ -982,7 +1146,7 @@ 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; + t_node *node; helper_node = ft_cget_node_child(connection, 0); if (!ft_strcmp(helper_node->token.type, g_defined_tokens[node_state].type)) @@ -997,13 +1161,131 @@ int set_state_from_connection(t_part *part, const t_parse_tree_node *connection) 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) + node = tie_bus(part, helper_node); + if (!node) return (1); - get_node_by_id(&part->nodes, id)->set_state = state; + node->set_state = state; return (0); } +t_node *get_node_from_spec(t_part *part, const t_parse_tree_node *pin_spec) +{ + size_t index; + t_id id; + t_pinbus *pinbus; + + pinbus = get_pinbus_from_spec(part, pin_spec); + if (!pinbus) + return (NULL); + if (pinbus->is_pin) + id = pinbus->pinbus.pin; + else + { + if (get_subbus_indeces(pinbus, pin_spec, &index, NULL)) + return (NULL); + id = *(t_id *)ft_vec_access(&pinbus->pinbus.bus, index); + } + if (!id) + return (NULL); + return (get_node_by_id(&part->nodes, id)); +} + +int add_pin_pin_connection(t_part *part, const t_parse_tree_node *connection) +{ + t_node *node1; + t_node *node2; + + node1 = get_node_from_spec(part, ft_cget_node_child(connection, 0)); + node2 = get_node_from_spec(part, ft_cget_node_child(connection, 2)); + if (!node1 || !node2) + return (1); + remap_ids(part, node1->id, node2->id); + return (merge_nodes(&part->nodes, &part->mosfets, node1, node2)); +} + +int connect_bus_pin(t_part *part, t_pinbus *pinbuses[2], size_t indexes[2]) +{ + t_id id; + t_node *nodes[2]; + + id = *(t_id *)ft_vec_access(&pinbuses[0]->pinbus.bus, indexes[0]); + nodes[0] = get_node_by_id(&part->nodes, id); + id = *(t_id *)ft_vec_access(&pinbuses[1]->pinbus.bus, indexes[1]); + nodes[1] = get_node_by_id(&part->nodes, id); + if (!nodes[0] || !nodes[1]) + return (1); + remap_ids(part, nodes[0]->id, nodes[1]->id); + return (merge_nodes(&part->nodes, &part->mosfets, nodes[0], nodes[1])); +} + +int add_bus_bus_connection(t_part *part, const t_parse_tree_node *connection) +{ + size_t start_bounds[2]; + size_t end_bounds[2]; + t_pinbus *pinbuses[2]; + + pinbuses[0] = get_pinbus_from_spec(part, ft_cget_node_child(connection, 0)); + pinbuses[1] = get_pinbus_from_spec(part, ft_cget_node_child(connection, 2)); + if (get_subbus_indeces(pinbuses[0], ft_cget_node_child(connection, 0), &start_bounds[0], &end_bounds[0]) + || get_subbus_indeces(pinbuses[1], ft_cget_node_child(connection, 2), &start_bounds[1], &end_bounds[1])) + return (1); + if (start_bounds[0] >= end_bounds[0]) + { + swap_indeces(&start_bounds[0], &end_bounds[0]); + swap_indeces(&start_bounds[1], &end_bounds[1]); + } + if (start_bounds[1] <= end_bounds[1]) + { + if (end_bounds[0] - start_bounds[0] != end_bounds[1] - start_bounds[1]) + return (1); + while (start_bounds[0] <= end_bounds[0]) + { + if (connect_bus_pin(part, pinbuses, start_bounds)) + return (1); + ++start_bounds[0]; + ++start_bounds[1]; + } + } + else + { + if (end_bounds[0] - start_bounds[0] != start_bounds[1] - end_bounds[1]) + return (1); + while (start_bounds[0] <= end_bounds[0]) + { + if (connect_bus_pin(part, pinbuses, start_bounds)) + return (1); + ++start_bounds[0]; + --start_bounds[1]; + } + } + return (0); +} + +int add_pin_bus_connection(t_part *part, const t_parse_tree_node *connection) +{ + const t_parse_tree_node *pin_spec; + const t_parse_tree_node *bus_spec; + t_node *node1; + t_node *node2; + + if (!ft_strcmp(ft_cget_node_child(connection, 1)->token.str, g_defined_tokens[widen_sign].str)) + { + pin_spec = ft_cget_node_child(connection, 0); + bus_spec = ft_cget_node_child(connection, 2); + } + else + { + pin_spec = ft_cget_node_child(connection, 2); + bus_spec = ft_cget_node_child(connection, 0); + } + node1 = tie_bus(part, bus_spec); + node2 = get_node_from_spec(part, pin_spec); + if (!node1 || !node2) + return (1); + remap_ids(part, node1->id, node2->id); + return (merge_nodes(&part->nodes, &part->mosfets, node1, node2)); +} + int add_connection(t_part *part, const t_parse_tree_node *connection) { if (is_state_setting_connection(connection)) @@ -1103,7 +1385,7 @@ int c_load(WINDOW *command_win, t_input input, t_vec *nodes, t_vec *mosfets) } parse_tree = ft_parse(&tokens, &parsing_table); ft_parsing_table_free(&parsing_table); - ft_vec_free(&tokens, NULL); + ft_vec_free(&tokens, free_token_void); if (parse_tree == NULL) { wprintw(command_win, "Could not parse file\n"); @@ -1111,9 +1393,11 @@ int c_load(WINDOW *command_win, t_input input, t_vec *nodes, t_vec *mosfets) } if (rewrite_graph(parse_tree, nodes, mosfets)) { + ft_parse_tree_free(parse_tree); wprintw(command_win, "Could not execute file\n"); return (1); } + ft_parse_tree_free(parse_tree); //rebuild_schema(nodes, mosfets); return (1); } diff --git a/src/main.c b/src/main.c index fa2949a..1f22ba1 100644 --- a/src/main.c +++ b/src/main.c @@ -28,6 +28,7 @@ void free_node(void *node) { ft_vec_free(&((t_node *)node)->connected, NULL); ft_vec_free(&((t_node *)node)->connected_gates, NULL); + ft_vec_free(&((t_node *)node)->segments, NULL); return ; }