typedef unsigned long t_id;
+extern const t_id INVALID_ID;
+
typedef enum e_orientation
{
UP = 0,
t_id id;
int is_opened;
t_type type;
- t_node *gate;
- t_node *source;
- t_node *drain;
+ t_id gate;
+ t_id source;
+ t_id drain;
t_position position;
t_orientation orientation;
} t_mosfet;
t_mosfet *add_mosfet(t_vec *mosfets, t_type type, t_position pos, t_orientation orient);
t_node *get_node_by_id(t_vec *nodes, t_id id);
t_mosfet *get_mosfet_by_id(t_vec *mosfets, t_id id);
-void bind_fet_node(t_mosfet *mosfet, t_node *node, t_terminal terminal);
-t_node *get_node_of_terminal(t_mosfet *mosfet, t_terminal terminal);
-int transfer_mosfet(t_mosfet *mosfet, t_node *from, t_node *to);
-int merge_nodes(t_node *node1, t_node *node2);
+void bind_fet_node(t_vec *nodes, t_mosfet *mosfet, t_node *node, t_terminal terminal);
+t_node *get_node_of_terminal(t_vec *nodes, const t_mosfet *mosfet, t_terminal terminal);
+int transfer_mosfet(t_vec *nodes, t_mosfet *mosfet, t_node *from, t_node *to);
+int merge_nodes(t_vec *nodes, t_vec *mosfets, t_node *node1, t_node *node2);
void free_node(void *node);
int process_input(t_windows *windows, t_vec *nodes, t_vec *mosfets);
int get_input(WINDOW *command_win, t_input *input);
const char *state_color_escape(t_state state);
-void draw_single(WINDOW *command_win, const t_mosfet *mosfet);
-void schema_draw_mosfet(WINDOW *schematics_win, const t_mosfet *mosfet);
+void draw_single(WINDOW *command_win, t_vec *nodes, const t_mosfet *mosfet);
+void schema_draw_mosfet(WINDOW *schematics_win, t_vec *nodes, const t_mosfet *mosfet);
void schema_draw_node(WINDOW *schematics_win, const t_node *node);
-void update_nodes(t_vec *nodes);
-int should_open(const t_mosfet *mosfet);
+void update_nodes(t_vec *nodes, t_vec *mosfets);
+int should_open(t_vec *nodes, const t_mosfet *mosfet);
int sim_step(t_vec *nodes, t_vec *mosfets);
void setup_terminal(t_windows *windows);
void apply_state(t_state state, t_vec *connected_nodes);
t_state reduce_state(t_state state);
-int c_addfet(WINDOW *command_win, t_input input, t_vec *mosfets);
+int c_addfet(WINDOW *command_win, t_input inputs, t_vec *mosfets);
int c_addnode(WINDOW *command_win, t_input input, t_vec *nodes);
int c_bind(WINDOW *command_win, t_input input, t_vec *nodes, t_vec *mosfets);
int c_connect(WINDOW *command_win, t_input input, t_vec *nodes, t_vec *mosfets);
-int c_draw(WINDOW *command_win, t_input input, t_vec *mosfets);
+int c_draw(WINDOW *command_win, t_input input, t_vec *nodes, t_vec *mosfets);
int c_help(WINDOW *command_win, t_input input);
int c_next(t_input input, t_vec *nodes, t_vec *mosfets);
int c_setnode(WINDOW *command_win, t_input input, t_vec *nodes);
#include "FET_sim.h"
#include "libft.h"
-int transfer_mosfet(t_mosfet *mosfet, t_node *from, t_node *to)
+const t_id INVALID_ID = 0;
+
+int transfer_mosfet(t_vec *nodes, t_mosfet *mosfet, t_node *from, t_node *to)
{
- if (mosfet->source == from)
- bind_fet_node(mosfet, to, source);
- if (mosfet->gate == from)
- bind_fet_node(mosfet, to, gate);
- if (mosfet->drain == from)
- bind_fet_node(mosfet, to, drain);
+ if (mosfet->source == from->id)
+ bind_fet_node(nodes, mosfet, to, source);
+ if (mosfet->gate == from->id)
+ bind_fet_node(nodes, mosfet, to, gate);
+ if (mosfet->drain == from->id)
+ bind_fet_node(nodes, mosfet, to, drain);
return (0);
}
-// node 2 should be erased perhaps?
-int merge_nodes(t_node *node1, t_node *node2)
+t_mosfet *get_connected(t_vec *mosfets, t_vec *connected, size_t ind)
+{
+ t_id mosfet_id;
+
+ mosfet_id = *(t_id *)ft_vec_access(connected, ind);
+ return (get_mosfet_by_id(mosfets, mosfet_id));
+}
+
+int node_identity(const void *, const void *);
+static void remove_node(t_vec *nodes, t_node *to_remove)
+{
+ size_t index;
+
+ if (ft_vec_find_index(nodes, to_remove, &index, node_identity) != success)
+ return ;
+ ft_vec_erase(nodes, index, free_node);
+ return ;
+}
+
+int merge_nodes(t_vec *nodes, t_vec *mosfets, t_node *node1, t_node *node2)
{
size_t i;
- t_mosfet **mosfet;
+ t_mosfet *mosfet;
t_node_segment *seg;
i = 0;
while (i < node2->connected.size)
{
- mosfet = ft_vec_access(&node2->connected, i);
- transfer_mosfet(*mosfet, node2, node1);
+ mosfet = get_connected(mosfets, &node2->connected, i);
+ transfer_mosfet(nodes, mosfet, node2, node1);
++i;
}
i = 0;
while (i < node2->connected_gates.size)
{
- mosfet = ft_vec_access(&node2->connected_gates, i);
- transfer_mosfet(*mosfet, node2, node1);
+ mosfet = get_connected(mosfets, &node2->connected_gates, i);
+ transfer_mosfet(nodes, mosfet, node2, node1);
++i;
}
i = 0;
ft_vec_append(&node1->segments, seg);
++i;
}
- ft_vec_forget_range(&node2->segments, node2->segments.size, 0);
+ remove_node(nodes, node2);
return (0);
}
-t_node *get_node_of_terminal(t_mosfet *mosfet, t_terminal terminal)
+t_node *get_node_of_terminal(t_vec *nodes, const t_mosfet *mosfet, t_terminal terminal)
{
if (terminal == source)
- return (mosfet->source);
+ return (get_node_by_id(nodes, mosfet->source));
if (terminal == gate)
- return (mosfet->gate);
+ return (get_node_by_id(nodes, mosfet->gate));
if (terminal == drain)
- return (mosfet->drain);
+ return (get_node_by_id(nodes, mosfet->drain));
return (NULL);
}
return (mosfet_identity(*mosfet1, *mosfet2));
}
-void bind_fet_node(t_mosfet *mosfet, t_node *node, t_terminal terminal)
+static int id_equality(const void *v_id1, const void *v_id2)
+{
+ return (*(t_id *)v_id1 - *(t_id *)v_id2);
+}
+
+void bind_fet_node(t_vec *nodes, t_mosfet *mosfet, t_node *node, t_terminal terminal)
{
- t_node *old;
+ t_node *old_node;
size_t index;
- old = NULL;
+ old_node = get_node_of_terminal(nodes, mosfet, terminal);
if (terminal == source)
{
- old = mosfet->source;
- mosfet->source = node;
- ft_vec_append(&node->connected, &mosfet);
- if (old && ft_vec_find_index(&node->connected, &mosfet, &index, mosfet_identity_indirect) == success)
- ft_vec_forget(&old->connected, index);
+ mosfet->source = node->id;
+ ft_vec_append(&node->connected, &(mosfet->id));
+ if (old_node && ft_vec_find_index(&node->connected, &(mosfet->id), &index, id_equality) == success)
+ ft_vec_forget(&old_node->connected, index);
}
else if (terminal == drain)
{
- old = mosfet->drain;
- mosfet->drain = node;
- ft_vec_append(&node->connected, &mosfet);
- if (old && ft_vec_find_index(&node->connected, &mosfet, &index, mosfet_identity_indirect) == success)
- ft_vec_forget(&old->connected, index);
+ mosfet->drain = node->id;
+ ft_vec_append(&node->connected, &(mosfet->id));
+ if (old_node && ft_vec_find_index(&node->connected, &(mosfet->id), &index, id_equality) == success)
+ ft_vec_forget(&old_node->connected, index);
}
else
{
- old = mosfet->gate;
- mosfet->gate = node;
- ft_vec_append(&node->connected_gates, &mosfet);
- if (old && ft_vec_find_index(&node->connected_gates, &mosfet, &index, mosfet_identity_indirect) == success)
- ft_vec_forget(&old->connected_gates, index);
+ mosfet->gate = node->id;
+ ft_vec_append(&node->connected_gates, &(mosfet->id));
+ if (old_node && ft_vec_find_index(&node->connected_gates, &(mosfet->id), &index, id_equality) == success)
+ ft_vec_forget(&old_node->connected_gates, index);
}
return ;
}
static t_id get_new_id(void)
{
- static t_id id = 0;
+ static t_id id = INVALID_ID + 1;
return (id++);
}
-// memset is used to initialize struct padding
t_node *add_node(t_vec *nodes, t_state set_state)
{
t_node node;
node.checked = 0;
node.state = set_state;
node.set_state = set_state;
- ft_vec_init(&node.connected, sizeof(t_mosfet *));
- ft_vec_init(&node.connected_gates, sizeof(t_mosfet *));
+ ft_vec_init(&node.connected, sizeof(t_id));
+ ft_vec_init(&node.connected_gates, sizeof(t_id));
ft_vec_init(&node.segments, sizeof(t_node_segment));
ft_vec_append(nodes, &node);
return (ft_vec_access(nodes, nodes->size - 1));
mosfet.id = get_new_id();
mosfet.is_opened = 0;
mosfet.type = type;
- mosfet.gate = NULL;
- mosfet.drain = NULL;
- mosfet.source = NULL;
+ mosfet.gate = INVALID_ID;
+ mosfet.drain = INVALID_ID;
+ mosfet.source = INVALID_ID;
mosfet.position = pos;
mosfet.orientation = orient;
ft_vec_append(mosfets, &mosfet);
return (1);
}
term = input.argv[2].val.terminal;
- bind_fet_node(mosfet, node, term);
+ bind_fet_node(nodes, mosfet, node, term);
return (1);
}
print_mosfet_id_error(command_win, input.argv[0].val.num);
return (1);
}
- term_node1 = get_node_of_terminal(mosfet1, input.argv[1].val.terminal);
+ term_node1 = get_node_of_terminal(nodes, mosfet1, input.argv[1].val.terminal);
mosfet2 = get_mosfet_by_id(mosfets, input.argv[2].val.num);
if (!mosfet2)
{
print_mosfet_id_error(command_win, input.argv[2].val.num);
return (1);
}
- term_node2 = get_node_of_terminal(mosfet2, input.argv[3].val.terminal);
+ term_node2 = get_node_of_terminal(nodes, mosfet2, input.argv[3].val.terminal);
if (term_node1 && term_node2)
- return (!merge_nodes(term_node1, term_node2));
+ return (!merge_nodes(nodes, mosfets, term_node1, term_node2));
else if (term_node1)
- bind_fet_node(mosfet2, term_node1, input.argv[3].val.terminal);
+ bind_fet_node(nodes, mosfet2, term_node1, input.argv[3].val.terminal);
else if (term_node2)
- bind_fet_node(mosfet1, term_node2, input.argv[1].val.terminal);
+ bind_fet_node(nodes, mosfet1, term_node2, input.argv[1].val.terminal);
else
{
new_node = add_node(nodes, unknown);
- bind_fet_node(mosfet1, new_node, input.argv[1].val.terminal);
- bind_fet_node(mosfet2, new_node, input.argv[3].val.terminal);
+ bind_fet_node(nodes, mosfet1, new_node, input.argv[1].val.terminal);
+ bind_fet_node(nodes, mosfet2, new_node, input.argv[3].val.terminal);
}
return (1);
}
#include "FET_sim.h"
#include "libft.h"
-int c_draw(WINDOW *command_win, t_input input, t_vec *mosfets)
+int c_draw(WINDOW *command_win, t_input input, t_vec *nodes, t_vec *mosfets)
{
size_t i;
const t_mosfet *mosfet;
while (i < mosfets->size)
{
mosfet = ft_vec_caccess(mosfets, i);
- draw_single(command_win, ft_vec_caccess(mosfets, i));
+ draw_single(command_win, nodes, ft_vec_caccess(mosfets, i));
++i;
}
}
if (!mosfet)
print_mosfet_id_error(command_win, input.argv[0].val.num);
else
- draw_single(command_win, mosfet);
+ draw_single(command_win, nodes, mosfet);
}
/*else
{
return (NC_RED);
}
-static t_nc_color get_switch_color(const t_mosfet *mosfet)
+static t_nc_color get_switch_color(t_vec *nodes, const t_mosfet *mosfet)
{
t_nc_color color;
if (mosfet->is_opened)
{
- if (mosfet->source)
- color = get_state_color(mosfet->source->state);
- else if (mosfet->drain)
- color = get_state_color(mosfet->drain->state);
+ if (mosfet->source != INVALID_ID)
+ color = get_state_color(get_node_of_terminal(nodes, mosfet, source)->state);
+ else if (mosfet->drain != INVALID_ID)
+ color = get_state_color(get_node_of_terminal(nodes, mosfet, drain)->state);
else
color = NC_RED;
}
return ;
}
-static void draw_switch(WINDOW *win, const t_mosfet *mosfet, t_orientation orientation)
+static void draw_switch(WINDOW *win, t_vec *nodes, const t_mosfet *mosfet, t_orientation orientation)
{
t_nc_color color;
t_switch_symbol_set set;
t_symbol switch_sym;
- color = get_switch_color(mosfet);
+ color = get_switch_color(nodes, mosfet);
set = get_switch_set(orientation);
- if (mosfet->is_opened && should_open(mosfet))
+ if (mosfet->is_opened && should_open(nodes, mosfet))
switch_sym = set.open;
- else if ((mosfet->is_opened && !should_open(mosfet))
- || (!mosfet->is_opened && should_open(mosfet)))
+ else if ((mosfet->is_opened && !should_open(nodes, mosfet))
+ || (!mosfet->is_opened && should_open(nodes, mosfet)))
switch_sym = set.transition;
else
switch_sym = set.closed;
return ;
}
-void schema_draw_mosfet(WINDOW *schematics_win, const t_mosfet *mosfet)
+void schema_draw_mosfet(WINDOW *schematics_win, t_vec *nodes, const t_mosfet *mosfet)
{
t_position old_pos;
t_position work_pos;
else if (mosfet->orientation == RIGHT)
--work_pos.x;
wmove(schematics_win, work_pos.y, work_pos.x);
- draw_switch(schematics_win, mosfet, mosfet->orientation);
+ draw_switch(schematics_win, nodes, mosfet, mosfet->orientation);
wmove(schematics_win, old_pos.y, old_pos.x);
return ;
}
return ;
}
-static void draw_top(WINDOW *command_win, const t_mosfet *mosfet)
+static void draw_top(WINDOW *command_win, t_vec *nodes, const t_mosfet *mosfet)
{
if (mosfet->source)
{
- wprintw(command_win, " %lu\n", mosfet->source->id);
- print_in_color(command_win, " |\n", get_state_color(mosfet->source->state));
+ wprintw(command_win, " %lu\n", mosfet->source);
+ print_in_color(command_win, " |\n", get_state_color(get_node_of_terminal(nodes, mosfet, source)->state));
}
else
{
return ;
}
-static void draw_middle(WINDOW *command_win, const t_mosfet *mosfet)
+static void draw_middle(WINDOW *command_win, t_vec *nodes, const t_mosfet *mosfet)
{
if (mosfet->gate)
{
- wprintw(command_win, "%4lu", mosfet->gate->id);
- print_in_color(command_win, "-", get_state_color(mosfet->gate->state));
+ wprintw(command_win, "%4lu", mosfet->gate);
+ print_in_color(command_win, "-", get_state_color(get_node_of_terminal(nodes, mosfet, gate)->state));
}
else
print_in_color(command_win, "NULL-", NC_RED);
waddch(command_win, mosfet->type);
- draw_switch(command_win, mosfet, LEFT);
+ draw_switch(command_win, nodes, mosfet, LEFT);
waddch(command_win, '\n');
return ;
}
-static void draw_bottom(WINDOW *command_win, const t_mosfet *mosfet)
+static void draw_bottom(WINDOW *command_win, t_vec *nodes, const t_mosfet *mosfet)
{
wprintw(command_win, " ");
if (mosfet->drain)
- print_in_color(command_win, "|\n", get_state_color(mosfet->drain->state));
+ print_in_color(command_win, "|\n", get_state_color(get_node_of_terminal(nodes, mosfet, drain)->state));
else
print_in_color(command_win, "|\n", NC_RED);
if (mosfet->drain)
- wprintw(command_win, " %lu", mosfet->drain->id);
+ wprintw(command_win, " %lu", mosfet->drain);
else
print_in_color(command_win, " NULL", NC_RED);
wprintw(command_win, "\n\n");
return ;
}
-void draw_single(WINDOW *command_win, const t_mosfet *mosfet)
+void draw_single(WINDOW *command_win, t_vec *nodes, const t_mosfet *mosfet)
{
- draw_top(command_win, mosfet);
- draw_middle(command_win, mosfet);
- draw_bottom(command_win, mosfet);
+ draw_top(command_win, nodes, mosfet);
+ draw_middle(command_win, nodes, mosfet);
+ draw_bottom(command_win, nodes, mosfet);
return ;
}
while (i < mosfets->size)
{
mosfet = ft_vec_caccess(mosfets, i);
- schema_draw_mosfet(schematics_win, mosfet);
+ schema_draw_mosfet(schematics_win, nodes, mosfet);
++i;
}
i = 0;
void free_node(void *node)
{
ft_vec_free(&((t_node *)node)->connected, NULL);
+ ft_vec_free(&((t_node *)node)->connected_gates, NULL);
return ;
}
if (input.command == next)
res = c_next(input, nodes, mosfets);
else if (input.command == draw)
- res = c_draw(windows->command_win, input, mosfets);
+ res = c_draw(windows->command_win, input, nodes, mosfets);
else if (input.command == setnode)
res = c_setnode(windows->command_win, input, nodes);
else if (input.command == addnode)
void cleanup(t_vec *nodes, t_vec *mosfets, t_windows *windows)
{
- update_nodes(NULL);
+ update_nodes(NULL, NULL);
ft_vec_free(nodes, free_node);
ft_vec_free(mosfets, NULL);
clean_terminal(windows);
}
-void add_terminal_nodes(WINDOW *schematics_win, t_vec *nodes, t_mosfet *mosfet)
+void add_terminal_node(WINDOW *schematics_win, t_vec *nodes, t_mosfet *mosfet, t_terminal terminal)
{
t_node *node;
node = add_node(nodes, floating);
- bind_fet_node(mosfet, node, source);
- node = add_node(nodes, floating);
- bind_fet_node(mosfet, node, gate);
- node = add_node(nodes, floating);
- bind_fet_node(mosfet, node, drain);
- add_terminal_segment(mosfet->source, mosfet, source);
- add_terminal_segment(mosfet->gate, mosfet, gate);
- add_terminal_segment(mosfet->drain, mosfet, drain);
- schema_draw_node(schematics_win, mosfet->source);
- schema_draw_node(schematics_win, mosfet->gate);
- schema_draw_node(schematics_win, mosfet->drain);
+ bind_fet_node(nodes, mosfet, node, terminal);
+ add_terminal_segment(node, mosfet, terminal);
+ schema_draw_node(schematics_win, node);
return ;
}
return ;
while (1)
{
- schema_draw_mosfet(schematics_win, mosfet);
+ schema_draw_mosfet(schematics_win, nodes, mosfet);
ch = wgetch(schematics_win);
if (ch == 'r' || ch == 'R')
{
mosfet->orientation = (mosfet->orientation - 1 + 4) % 4;
else
{
- add_terminal_nodes(schematics_win, nodes, mosfet);
+ add_terminal_node(schematics_win, nodes, mosfet, source);
+ add_terminal_node(schematics_win, nodes, mosfet, gate);
+ add_terminal_node(schematics_win, nodes, mosfet, drain);
wmove(schematics_win, mosfet->position.y, mosfet->position.x);
ungetch(ch);
return ;
#include "libft.h"
// Maybe an error should be return when gate is NULL
-int should_open(const t_mosfet *mosfet)
+int should_open(t_vec *nodes, const t_mosfet *mosfet)
{
- if (!mosfet->gate)
+ if (mosfet->gate == INVALID_ID)
return (0);
- return ((mosfet->type == p && mosfet->gate->state == off)
- || (mosfet->type == n && mosfet->gate->state == on));
+ return ((mosfet->type == p && get_node_of_terminal(nodes, mosfet, gate)->state == off)
+ || (mosfet->type == n && get_node_of_terminal(nodes, mosfet, gate)->state == on));
}
-static void update_mosfets(t_vec *mosfets)
+static void update_mosfets(t_vec *nodes, t_vec *mosfets)
{
size_t i;
t_mosfet *mosfet;
while (i < mosfets->size)
{
mosfet = ft_vec_access(mosfets, i);
- mosfet->is_opened = should_open(mosfet);
+ mosfet->is_opened = should_open(nodes, mosfet);
++i;
}
return ;
int sim_step(t_vec *nodes, t_vec *mosfets)
{
- update_mosfets(mosfets);
- update_nodes(nodes);
+ update_mosfets(nodes, mosfets);
+ update_nodes(nodes, mosfets);
return (1);
}
#include "libft.h"
#include <stdlib.h>
-static t_node *get_neighbour_node(const t_mosfet *mosfet, const t_node *start)
+static t_node *get_neighbour_node(t_vec *nodes, const t_mosfet *mosfet, const t_node *start)
{
- if (mosfet->source == start)
- return (mosfet->drain);
- return (mosfet->source);
+ if (mosfet->source == start->id)
+ return (get_node_of_terminal(nodes, mosfet, drain));
+ return (get_node_of_terminal(nodes, mosfet, source));
}
-static void find_connected(t_node *node, t_vec *connected_nodes)
+static void find_connected(t_vec *nodes, t_vec *mosfets, t_node *node, t_vec *connected_nodes)
{
size_t i;
t_node *neigh_node;
i = 0;
while (i < node->connected.size)
{
- mosfet = *(t_mosfet **)ft_vec_access(&node->connected, i);
+ mosfet = get_mosfet_by_id(mosfets, *(t_id *)ft_vec_access(&node->connected, i));
if (mosfet->is_opened)
{
- neigh_node = get_neighbour_node(mosfet, node);
- find_connected(neigh_node, connected_nodes);
+ neigh_node = get_neighbour_node(nodes, mosfet, node);
+ find_connected(nodes, mosfets, neigh_node, connected_nodes);
}
++i;
}
// so I provide this mechanism. It may be removed in the future if
// it seems to be a reasonable decision.
-void update_nodes(t_vec *nodes)
+void update_nodes(t_vec *nodes, t_vec *mosfets)
{
size_t i;
t_state state;
cur_node = ft_vec_access(nodes, i);
if (!cur_node->checked)
{
- find_connected(cur_node, &connected_nodes);
+ find_connected(nodes, mosfets, cur_node, &connected_nodes);
state = resolve_state(&connected_nodes);
apply_state(reduce_state(state), &connected_nodes);
ft_vec_forget_range(&connected_nodes, connected_nodes.size, 0);