Skip to content

WIP: Implement inout support into ODIN II #1292

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion ODIN_II/SRC/ast_elaborate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2656,11 +2656,11 @@ void create_param_table_for_scope(ast_node_t* module_items, sc_hierarchy* local_
/* symbols are already dealt with */
if (var_declare->types.variable.is_input
|| var_declare->types.variable.is_output
|| var_declare->types.variable.is_inout
|| var_declare->types.variable.is_reg
|| var_declare->types.variable.is_genvar
|| var_declare->types.variable.is_wire
|| var_declare->types.variable.is_defparam)

continue;

oassert(module_items->children[i]->children[j]->type == VAR_DECLARE);
Expand Down
132 changes: 71 additions & 61 deletions ODIN_II/SRC/netlist_create_from_ast.cpp

Large diffs are not rendered by default.

33 changes: 25 additions & 8 deletions ODIN_II/SRC/netlist_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,8 @@ nnet_t* allocate_nnet() {
*-------------------------------------------------------------------------------------------*/
nnet_t* free_nnet(nnet_t* to_free) {
if (to_free) {
to_free->fanout_pins = (npin_t**)vtr::free(to_free->fanout_pins);
if (to_free->num_fanout_pins)
to_free->fanout_pins = (npin_t**)vtr::free(to_free->fanout_pins);

if (to_free->name)
vtr::free(to_free->name);
Expand Down Expand Up @@ -417,13 +418,13 @@ void add_driver_pin_to_net(nnet_t* net, npin_t* pin) {
* The lasting one is input, and output disappears
*-------------------------------------------------------------------------------------------*/
void combine_nets(nnet_t* output_net, nnet_t* input_net, netlist_t* netlist) {
/* in case there are any fanouts in output net (should only be zero and one nodes) */
join_nets(input_net, output_net);
/* copy the driver over to the new_net */
for (int i = 0; i < output_net->num_driver_pins; i++) {
/* IF - there is a pin assigned to this net, then copy it */
add_driver_pin_to_net(input_net, output_net->driver_pins[i]);
}
/* in case there are any fanouts in output net (should only be zero and one nodes) */
join_nets(input_net, output_net);
/* mark that this is combined */
input_net->combined = true;

Expand Down Expand Up @@ -465,11 +466,27 @@ void join_nets(nnet_t* join_to_net, nnet_t* other_net) {
}

error_message(NETLIST, unknown_location, "%s", "Found a combinational loop");
} else if (other_net->num_driver_pins > 1) {
if (other_net->name && join_to_net->name)
error_message(NETLIST, unknown_location, "Tried to join net %s to %s but this would lose %d drivers for net %s", other_net->name, join_to_net->name, other_net->num_driver_pins - 1, other_net->name);
else
error_message(NETLIST, unknown_location, "Tried to join nets but this would lose %d drivers", other_net->num_driver_pins - 1);
} else if (other_net->num_driver_pins > 1 && join_to_net->num_driver_pins != 0) {
bool drivers_match = true;
if(other_net->num_driver_pins == join_to_net->num_driver_pins) {
for (int i = 0; drivers_match && i < other_net->num_driver_pins; i++)
{
bool driver_match = false;
for (int j = 0; !driver_match && j < join_to_net->num_driver_pins; j++)
{
driver_match = join_to_net->driver_pins[j] == other_net->driver_pins[i];
}
drivers_match &= driver_match;
}
}
// Either we tried to eliminate a buffer into a net with multiple drivers
// or we tried to combine nets that already had mismatching drivers
if(!drivers_match) {
if (other_net->name && join_to_net->name)
error_message(NETLIST, unknown_location, "Tried to join net %s to %s but this would lose %d drivers for net %s", other_net->name, join_to_net->name, other_net->num_driver_pins - 1, other_net->name);
else
error_message(NETLIST, unknown_location, "Tried to join nets but this would lose %d drivers", other_net->num_driver_pins - 1);
}
}

/* copy the driver over to the new_net */
Expand Down
94 changes: 51 additions & 43 deletions ODIN_II/SRC/output_blif.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,25 +65,24 @@ static bool warn_undriven(nnode_t* node, nnet_t* net) {
return false;
}

// TODO Uncomment this for In Outs
//static void merge_with_inputs(nnode_t* node, long pin_idx) {
// oassert(pin_idx < node->num_input_pins);
// nnet_t* net = node->input_pins[pin_idx]->net;
// warn_undriven(node, net);
// // Merge node with all inputs with fanout of 1
// if (net->num_fanout_pins <= 1) {
// for (int i = 0; i < net->num_driver_pins; i++) {
// npin_t* driver = net->driver_pins[i];
// if (driver->name != NULL && ((driver->node->type == MULTIPLY) || (driver->node->type == HARD_IP) || (driver->node->type == MEMORY) || (driver->node->type == ADD) || (driver->node->type == MINUS))) {
// vtr::free(driver->name);
// driver->name = vtr::strdup(node->name);
// } else {
// vtr::free(driver->node->name);
// driver->node->name = vtr::strdup(node->name);
// }
// }
// }
//}
static void merge_with_inputs(nnode_t* node, long pin_idx) {
oassert(pin_idx < node->num_input_pins);
nnet_t* net = node->input_pins[pin_idx]->net;
warn_undriven(node, net);
// Merge node with all inputs with fanout of 1
if (net->num_fanout_pins <= 1) {
for (int i = 0; i < net->num_driver_pins; i++) {
npin_t* driver = net->driver_pins[i];
if (driver->name != NULL && ((driver->node->type == MULTIPLY) || (driver->node->type == HARD_IP) || (driver->node->type == MEMORY) || (driver->node->type == ADD) || (driver->node->type == MINUS))) {
vtr::free(driver->name);
driver->name = vtr::strdup(node->name);
} else {
vtr::free(driver->node->name);
driver->node->name = vtr::strdup(node->name);
}
}
}
}

static void print_net_driver(FILE* out, nnode_t* node, nnet_t* net, long driver_idx) {
oassert(driver_idx < net->num_driver_pins);
Expand Down Expand Up @@ -133,21 +132,27 @@ static void print_output_pin(FILE* out, nnode_t* node) {
fprintf(out, " %s", node->name);
}

static char* buffer_multi_drivers(FILE* out, nnode_t* node, long pin_idx)
{
nnet_t* net = node->input_pins[pin_idx]->net;
if (net->num_driver_pins > 1) {
char* name = op_node_name(BUF_NODE, node->name);
// Assign each driver to the implicit buffer
for (int j = 0; j < net->num_driver_pins; j++) {
fprintf(out, ".names");
print_net_driver(out, node, net, j);
fprintf(out, " %s\n1 1\n\n", name);
}
return name;
}
return NULL;
}

static void print_dot_names_header(FILE* out, nnode_t* node) {
char** names = (char**)vtr::calloc(node->num_input_pins, sizeof(char*));

// Create an implicit buffer if there are multiple drivers to the component
for (int i = 0; i < node->num_input_pins; i++) {
nnet_t* input_net = node->input_pins[i]->net;
if (input_net->num_driver_pins > 1) {
names[i] = op_node_name(BUF_NODE, node->name);
// Assign each driver to the implicit buffer
for (int j = 0; j < input_net->num_driver_pins; j++) {
fprintf(out, ".names");
print_net_driver(out, node, input_net, j);
fprintf(out, " %s\n1 1\n\n", names[i]);
}
}
names[i] = buffer_multi_drivers(out, node, i);
}

// Print the actual header
Expand Down Expand Up @@ -221,14 +226,13 @@ void output_blif(FILE* out, netlist_t* netlist) {
fprintf(out, "\n.names gnd\n.names unconn\n.names vcc\n1\n");
fprintf(out, "\n");

// TODO Uncomment this for In Outs
// connect all the outputs up to the last gate
// for (long i = 0; i < netlist->num_top_output_nodes; i++) {
// nnode_t* node = netlist->top_output_nodes[i];
// for (int j = 0; j < node->num_input_pins; j++) {
// merge_with_inputs(node, j);
// }
// }
for (long i = 0; i < netlist->num_top_output_nodes; i++) {
nnode_t* node = netlist->top_output_nodes[i];
for (int j = 0; j < node->num_input_pins; j++) {
merge_with_inputs(node, j);
}
}

/* traverse the internals of the flat net-list */
if (strcmp(configuration.output_type.c_str(), "blif") == 0) {
Expand All @@ -241,8 +245,7 @@ void output_blif(FILE* out, netlist_t* netlist) {
for (long i = 0; i < netlist->num_top_output_nodes; i++) {
nnode_t* node = netlist->top_output_nodes[i];

// TODO Change this to > 1 for In Outs
if (node->input_pins[0]->net->num_fanout_pins > 0) {
if (node->input_pins[0]->net->num_fanout_pins > 1) {
nnet_t* net = node->input_pins[0]->net;
warn_undriven(node, net);
for (int j = 0; j < net->num_driver_pins; j++) {
Expand Down Expand Up @@ -541,21 +544,26 @@ void define_ff(nnode_t* node, FILE* out) {
// grab the edge sensitivity of the flip flop
const char* edge_type_str = edge_type_blif_str(node);

std::string input;
std::string output;
std::string clock_driver;
char* input_driver = buffer_multi_drivers(out, node, 0);

fprintf(out, ".latch");

/* input */
print_input_single_driver(out, node, 0);
if(!input_driver)
print_input_single_driver(out, node, 0);
else {
// Use the implicit buffer we created before
fprintf(out, " %s", input_driver);
vtr::free(input_driver);
}

/* output */
print_output_pin(out, node);

/* sensitivity */
fprintf(out, " %s", edge_type_str);

// TODO Should clocks support mutliple drivers?
/* clock */
print_input_single_driver(out, node, 1);

Expand Down
Loading