VPR-6.0

vpr/SRC/pack/ff_pack.c File Reference

#include <assert.h>
#include <stdio.h>
#include <string.h>
#include "util.h"
#include "vpr_types.h"
#include "globals.h"
#include "ff_pack.h"
Include dependency graph for ff_pack.c:

Go to the source code of this file.

Functions

void absorb_buffer_luts ()
void compress_netlist ()
booleanalloc_and_load_is_clock (boolean global_clocks)

Function Documentation

void absorb_buffer_luts ( )

This routine uses a simple pattern matching algorithm to remove buffer LUTs where possible (single-input LUTs that are programmed to be a wire)

Definition at line 10 of file ff_pack.c.

                          {

        int bnum, in_blk, out_blk, ipin, out_net, in_net;
        int removed = 0;

        /* Pin ordering for the clb blocks (1 VPACK_LUT + 1 FF in each logical_block) is      *
        * output, n VPACK_LUT inputs, clock input.                                   */

        for (bnum=0;bnum<num_logical_blocks;bnum++) {
                if (strcmp(logical_block[bnum].model->name, "names") == 0) {
                        if(logical_block[bnum].truth_table != NULL && logical_block[bnum].truth_table->data_vptr) {
                                if(strcmp("0 0", (char*)logical_block[bnum].truth_table->data_vptr) == 0 ||
                                        strcmp("1 1", (char*)logical_block[bnum].truth_table->data_vptr) == 0)
                                {
                                        for(ipin = 0; ipin < logical_block[bnum].model->inputs->size; ipin++) {
                                                if(logical_block[bnum].input_nets[0][ipin] == OPEN)
                                                        break;
                                        }
                                        assert(ipin == 1);

                                        assert(logical_block[bnum].clock_net == OPEN);
                                        assert(logical_block[bnum].model->inputs->next == NULL);
                                        assert(logical_block[bnum].model->outputs->size == 1);
                                        assert(logical_block[bnum].model->outputs->next == NULL);
                                        
                                        in_net = logical_block[bnum].input_nets[0][0];   /* Net driving the buffer */
                                        out_net = logical_block[bnum].output_nets[0][0];   /* Net the buffer us driving */
                                        out_blk = vpack_net[out_net].node_block[1];
                                        in_blk = vpack_net[in_net].node_block[0];

                                        assert(in_net != OPEN);
                                        assert(out_net != OPEN);
                                        assert(out_blk != OPEN);
                                        assert(in_blk != OPEN);
                                        
                                        /* TODO: Make this handle general cases, due to time reasons I can only handle buffers with single outputs */
                                        if (vpack_net[out_net].num_sinks == 1) {
                                                for(ipin = 1; ipin <= vpack_net[in_net].num_sinks; ipin++) {
                                                        if(vpack_net[in_net].node_block[ipin] == bnum) {
                                                                break;
                                                        }
                                                }
                                                assert(ipin <= vpack_net[in_net].num_sinks);
                                                 
                                                vpack_net[in_net].node_block[ipin] = vpack_net[out_net].node_block[1];  /* New output */
                                                vpack_net[in_net].node_block_port[ipin] = vpack_net[out_net].node_block_port[1];
                                                vpack_net[in_net].node_block_pin[ipin] = vpack_net[out_net].node_block_pin[1];

                                                assert(logical_block[out_blk].input_nets[vpack_net[out_net].node_block_port[1]][vpack_net[out_net].node_block_pin[1]] == out_net);
                                                logical_block[out_blk].input_nets[vpack_net[out_net].node_block_port[1]][vpack_net[out_net].node_block_pin[1]] = in_net;
                                                
                                                vpack_net[out_net].node_block[0] = OPEN; /* This vpack_net disappears; mark. */
                                                vpack_net[out_net].node_block_pin[0] = OPEN; /* This vpack_net disappears; mark. */
                                                vpack_net[out_net].node_block_port[0] = OPEN; /* This vpack_net disappears; mark. */
                                                vpack_net[out_net].num_sinks = 0; /* This vpack_net disappears; mark. */
                                                
                                                logical_block[bnum].type = VPACK_EMPTY;   /* Mark logical_block that had LUT */
                                                
                                                /* error checking */
                                                for (ipin=0;ipin<=vpack_net[out_net].num_sinks;ipin++) {
                                                        assert(vpack_net[out_net].node_block[ipin] != bnum);
                                                }
                                                removed++;
                                        }
                                }
                        }
                }
        }
        printf("Removed %d LUT buffers \n", removed);
}

Here is the caller graph for this function:

boolean* alloc_and_load_is_clock ( boolean  global_clocks)

Looks through all the logical_block to find and mark all the clocks, by setting the corresponding entry in is_clock to true. global_clocks is used only for an error check.

Definition at line 258 of file ff_pack.c.

                                                         {

        int num_clocks, bnum, clock_net;
        boolean *is_clock;

        num_clocks = 0;

        is_clock = (boolean *) my_calloc (num_logical_nets, sizeof(boolean));

        /* Want to identify all the clock nets.  */

        for (bnum=0;bnum<num_logical_blocks;bnum++) {
                if(logical_block[bnum].type == VPACK_LATCH) {
                        clock_net = logical_block[bnum].clock_net;
                        assert(clock_net != OPEN);
                        if (is_clock[clock_net] == FALSE) {
                                is_clock[clock_net] = TRUE;
                                num_clocks++;
                        }
                } else {
                        if(logical_block[bnum].clock_net != OPEN) {
                                clock_net = logical_block[bnum].clock_net;
                                if (is_clock[clock_net] == FALSE) {
                                        is_clock[clock_net] = TRUE;
                                        num_clocks++;
                                }
                        }
                }
        }

        /* If we have multiple clocks and we're supposed to declare them global, *
        * print a warning message, since it looks like this circuit may have    *
        * locally generated clocks.                                             */

        if (num_clocks > 1 && global_clocks) {
                printf("Warning:  circuit contains %d clocks.\n", num_clocks);
                printf("          All will be marked global.\n");
        }

        return (is_clock);
}

Here is the call graph for this function:

Here is the caller graph for this function:

void compress_netlist ( )

This routine removes all the VPACK_EMPTY blocks and OPEN nets that may have been created by the ff_pack routine. After this routine, all the VPACK_LUT+FF blocks that exist in the netlist are in a contiguous list with no unused spots. The same goes for the list of nets. This means that blocks and nets have to be renumbered somewhat.

Definition at line 88 of file ff_pack.c.

                         {
 int inet, iblk, index, ipin, new_num_nets, new_num_blocks, i;
 int *net_remap, *block_remap;
 int num_nets;
 t_model_ports *port;
 struct s_linked_vptr *tvptr, *next;

 new_num_nets = 0;
 new_num_blocks = 0;
 net_remap = my_malloc (num_logical_nets * sizeof(int));
 block_remap = my_malloc (num_logical_blocks * sizeof(int));

 for (inet=0;inet<num_logical_nets;inet++) {
         if (vpack_net[inet].node_block[0] != OPEN) {
       net_remap[inet] = new_num_nets;
       new_num_nets++;
    }
    else {
       net_remap[inet] = OPEN;
    }
 }

 for (iblk=0;iblk<num_logical_blocks;iblk++) {
    if (logical_block[iblk].type != VPACK_EMPTY) {
       block_remap[iblk] = new_num_blocks;
       new_num_blocks++;
    }
    else {
       block_remap[iblk] = OPEN;
    }
 }

 
 if (new_num_nets != num_logical_nets || new_num_blocks != num_logical_blocks) {

    for (inet=0;inet<num_logical_nets;inet++) {
                if (vpack_net[inet].node_block[0] != OPEN) {
          index = net_remap[inet];
          vpack_net[index] = vpack_net[inet];
                  for (ipin = 0; ipin <= vpack_net[index].num_sinks; ipin++) 
                  {
                          vpack_net[index].node_block[ipin] = block_remap[vpack_net[index].node_block[ipin]];
                  }
       }
       else {
          free (vpack_net[inet].name);
                  free (vpack_net[inet].node_block);
                  free (vpack_net[inet].node_block_port);
                  free (vpack_net[inet].node_block_pin);
       }
    }
  
    num_logical_nets = new_num_nets;
    vpack_net = (struct s_net *) my_realloc (vpack_net, 
             num_logical_nets * sizeof (struct s_net));

    for (iblk=0;iblk<num_logical_blocks;iblk++) {
       if (logical_block[iblk].type != VPACK_EMPTY) {
          index = block_remap[iblk];
                  if(index != iblk) {
                        logical_block[index] = logical_block[iblk];
                  }

                  num_nets = 0;
                  port = logical_block[index].model->inputs;
                  while(port) {
                          for(ipin = 0; ipin < port->size; ipin++) {
                                  if(port->is_clock) {
                                          assert(port->size == 1 && port->index == 0 && ipin == 0);
                                          if(logical_block[index].clock_net == OPEN)
                                                continue;
                                          logical_block[index].clock_net =
                                                net_remap[logical_block[index].clock_net];
                                  } else {
                                        if(logical_block[index].input_nets[port->index][ipin] == OPEN)
                                          continue;
                                        logical_block[index].input_nets[port->index][ipin] =
                                                net_remap[logical_block[index].input_nets[port->index][ipin]];
                                  }
                                num_nets++;
                  }
                          port = port->next;
                  }

                  port = logical_block[index].model->outputs;
                  while(port) {
                          for(ipin = 0; ipin < port->size; ipin++) {
                                  if(logical_block[index].output_nets[port->index][ipin] == OPEN)
                                          continue;
                                logical_block[index].output_nets[port->index][ipin] =
                                        net_remap[logical_block[index].output_nets[port->index][ipin]];
                                num_nets++;
                  }
                          port = port->next;
                  }
       }

       else {
                        free (logical_block[iblk].name);
                        port = logical_block[iblk].model->inputs;
                        i = 0;
                        while(port) {
                                if(!port->is_clock) {
                                        if(logical_block[iblk].input_nets) {
                                                if(logical_block[iblk].input_nets[i]) {
                                                        free(logical_block[iblk].input_nets[i]);
                                                        logical_block[iblk].input_nets[i] = NULL;
                                                }
                                        }
                                        i++;
                                }
                                port = port->next;
                        }
                        if(logical_block[iblk].input_nets)
                                free(logical_block[iblk].input_nets);
                        port = logical_block[iblk].model->outputs;
                        i = 0;
                        while(port) {
                                if(logical_block[iblk].output_nets) {
                                        if(logical_block[iblk].output_nets[i]) {
                                                free(logical_block[iblk].output_nets[i]);
                                                logical_block[iblk].output_nets[i] = NULL;
                                        }
                                }
                                i++;
                                port = port->next;
                        }
                        if(logical_block[iblk].output_nets)
                                free(logical_block[iblk].output_nets);
                        tvptr = logical_block[iblk].truth_table;
                        while(tvptr != NULL) {
                                if(tvptr->data_vptr)
                                        free(tvptr->data_vptr);
                                next = tvptr->next;
                                free(tvptr);
                                tvptr = next;
                        }
       }
    }

        printf("Sweeped away %d nodes\n", num_logical_blocks - new_num_blocks);

    num_logical_blocks = new_num_blocks;
    logical_block = (struct s_logical_block *) my_realloc (logical_block, 
              num_logical_blocks * sizeof (struct s_logical_block));
 }

/* Now I have to recompute the number of primary inputs and outputs, since *
 * some inputs may have been unused and been removed.  No real need to     *
 * recount primary outputs -- it's just done as defensive coding.          */

 num_p_inputs = 0;
 num_p_outputs = 0;
 
 for (iblk=0;iblk<num_logical_blocks;iblk++) {
    if (logical_block[iblk].type == VPACK_INPAD) 
       num_p_inputs++;
    else if (logical_block[iblk].type == VPACK_OUTPAD) 
       num_p_outputs++;
 }
 
 
 free (net_remap);
 free (block_remap);
}

Here is the call graph for this function:

Here is the caller graph for this function: