blob: bd1d77c92545a56d66d988bf857be87ec4280d85 [file] [log] [blame]
// netlist.cpp
//
// Created by Daniel Schwartz-Narbonne on 14/04/07.
//
// Copyright 2007 Princeton University
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
#include "location_t.h"
#include "netlist.h"
#include "netlist_elem.h"
#include "rng.h"
#include <fstream>
#include <iostream>
#include <assert.h>
using namespace std;
void netlist::release(netlist_elem* elem)
{
return;
}
//*****************************************************************************************
//not thread safe, tho i could make it so if i needed to
//only look at the non_blank elements: this saves some time
//*****************************************************************************************
routing_cost_t netlist::total_routing_cost()
{
routing_cost_t rval = 0;
for (std::map<std::string, netlist_elem*>::iterator iter = _elem_names.begin();
iter != _elem_names.end();
++iter){
netlist_elem* elem = iter->second;
rval += elem->routing_cost_given_loc(*(elem->present_loc.Get()));
}
return rval / 2; //since routing_cost calculates both input and output routing, we have double counted
}
//*****************************************************************************************
// just use a simple shuffle algorithm
//*****************************************************************************************
void netlist::shuffle(Rng* rng)
{
for (int i = 0; i < _max_x * _max_y * 1000; i++){
netlist_elem *a, *b;
get_random_pair(&a, &b, rng);
swap_locations(a, b);
}
}
//*****************************************************************************************
// SYNC need chris' atomic swap algorithm
//*****************************************************************************************
void netlist::swap_locations(netlist_elem* elem_a, netlist_elem* elem_b)
{
//and swap the locations stored in the actual netlist_elem
elem_a->present_loc.Swap(elem_b->present_loc);
}
//*****************************************************************************************
//returns an elemment that is different from the different_from element
// if different_from == NO_MATCHING_ELEMENT then returns any element
//*****************************************************************************************
netlist_elem* netlist::get_random_element(long* elem_id, long different_from, Rng* rng)
{
long id = rng->rand(_chip_size);
netlist_elem* elem = &(_elements[id]);
//loop until we get a non duplicate element
//-1 is not a possible element, will never enter this loop in that case
//if it doesn't work, try a new one
while (id == different_from){
id = rng->rand(_chip_size);
elem = &(_elements[id]);
}
*elem_id=id;
return elem;
}
//*****************************************************************************************
//assumption: will return elements a, b which we can get a valid lock on
//*****************************************************************************************
void netlist::get_random_pair(netlist_elem** a, netlist_elem** b, Rng* rng)
{
//get a random element
long id_a = rng->rand(_chip_size);
netlist_elem* elem_a = &(_elements[id_a]);
//now do the same for b
long id_b = rng->rand(_chip_size);
netlist_elem* elem_b = &(_elements[id_b]);
//keep trying new elements until we get one that works
//get required locks automatically rolls back if it fails
//keep going until we get
while (id_b == id_a){ //no duplicate elements
//if it doesn't work, try a new one
id_b = rng->rand(_chip_size);
elem_b = &(_elements[id_b]);
}
*a = elem_a;
*b = elem_b;
return;
}
//*****************************************************************************************
// No longer easy to implement
//*****************************************************************************************
netlist_elem* netlist::netlist_elem_from_loc(location_t& loc)
{
assert(false);
return NULL;
}
//*****************************************************************************************
//
//*****************************************************************************************
netlist_elem* netlist::netlist_elem_from_name(std::string& name)
{
return (_elem_names[name]);
}
//*****************************************************************************************
// TODO add errorchecking
// ctor. Takes a properly formatted input file, and converts it into a
//*****************************************************************************************
netlist::netlist(const std::string& filename)
{
ifstream fin (filename.c_str());
assert(fin.is_open()); // were there any errors on opening?
//read the chip_array paramaters
fin >> _num_elements >> _max_x >> _max_y;
_chip_size = _max_x * _max_y;
assert(_num_elements < _chip_size);
//create a chip of the right size
_elements.resize(_chip_size);
cout << "locs created" << endl;
//create the location elements
vector<location_t> y_vec(_max_y);
_locations.resize(_max_x, y_vec);
//and set each one to its correct value
unsigned i_elem = 0;
for (int x = 0; x < _max_x; x++){
for (int y = 0; y < _max_y; y++){
location_t* loc = &_locations.at(x).at(y);
loc->x = x;
loc->y = y;
_elements.at(i_elem).present_loc.Set(loc);
i_elem++;
}//for (int y = 0; y < _max_y; y++)
}//for (int x = 0; x < _max_x; x++)
cout << "locs assigned" << endl;
int i=0;
while (!fin.eof()){
i++;
if ((i % 100000) == 0){
cout << "Just saw element: " << i << endl;
}
std::string name;
fin >> name;
netlist_elem* present_elem = create_elem_if_necessary(name); // the element that we are presently working on
//use create if necessary because it might have been created as a previous elements fanin
//set the basic info for the element
present_elem->item_name = name; //its name
int type; //its type TODO errorcheck here
fin >> type; // presently, don't actually use this
std::string fanin_name;
while (fin >> fanin_name){
if (fanin_name == "END"){
break; //last element in fanin
} //otherwise, make present elem the fanout of fanin_elem, and vice versa
netlist_elem* fanin_elem = create_elem_if_necessary(fanin_name);
present_elem->fanin.push_back(fanin_elem);
fanin_elem->fanout.push_back(present_elem);
}//while (fin >> fanin_name)
}//while (!fin.eof())
cout << "netlist created. " << i-1 << " elements." << endl;
}
//*****************************************************************************************
// Used in the ctor. Since an element have fanin from an element that can occur both
// earlier and later in the input file, we must handle both cases
//*****************************************************************************************
netlist_elem* netlist::create_elem_if_necessary(std::string& name)
{
static unsigned unused_elem = 0;//the first unused element
netlist_elem* rval;
//check whether we already have a netlist element with that name
std::map<std::string, netlist_elem*>::iterator iter = _elem_names.find(name);
if (iter == _elem_names.end()){
rval = &_elements.at(unused_elem);//if not, get one from the _elements pool
_elem_names[name] = rval;//put it in the map
unused_elem++;
} else {
//if it is in the map, just get a pointer to it
rval = iter->second;
}
return rval;
}
//*****************************************************************************************
// simple dump file
// not threadsafe
//*****************************************************************************************
void netlist::print_locations(const std::string& filename)
{
ofstream fout(filename.c_str());
assert(fout.is_open());
for (std::map<std::string, netlist_elem*>::iterator iter = _elem_names.begin();
iter != _elem_names.end();
++iter){
netlist_elem* elem = iter->second;
fout << elem->item_name << "\t" << elem->present_loc.Get()->x << "\t" << elem->present_loc.Get()->y << std::endl;
}
}