#include "funcnode.h"
FuncNode::FuncNode() :
+ predicate_tree_initialized(false),
func_inst_map(),
inst_list(),
- entry_insts()
+ entry_insts(),
+ thrd_read_map()
{}
-/* Check whether FuncInst with the same type, position, and location
+/* Check whether FuncInst with the same type, position, and location
* as act has been added to func_inst_map or not. If so, return it;
* if not, add it and return it.
*
* @return FuncInst with the same type, position, and location as act */
-FuncInst * FuncNode::get_or_add_action(ModelAction *act)
+FuncInst * FuncNode::get_or_add_inst(ModelAction *act)
{
ASSERT(act);
const char * position = act->get_position();
func_inst = new FuncInst(act, this);
inst->get_collisions()->push_back(func_inst);
- inst_list.push_back(func_inst); // delete?
- if (func_inst->is_read())
- group_reads_by_loc(func_inst);
+ inst_list.push_back(func_inst); // delete?
return func_inst;
}
}
FuncInst * func_inst = new FuncInst(act, this);
+
func_inst_map.put(position, func_inst);
inst_list.push_back(func_inst);
- if (func_inst->is_read())
- group_reads_by_loc(func_inst);
-
return func_inst;
}
if (inst == NULL)
return;
- func_inst_list_mt::iterator it;
- for (it = entry_insts.begin(); it != entry_insts.end(); it++) {
- if (inst == *it)
+ mllnode<FuncInst*>* it;
+ for (it = entry_insts.begin(); it != NULL; it = it->getNext()) {
+ if (inst == it->getVal())
return;
}
entry_insts.push_back(inst);
}
-/* group atomic read actions by memory location */
-void FuncNode::group_reads_by_loc(FuncInst * inst)
+/* @param act_list a list of ModelActions; this argument comes from ModelExecution
+ * convert act_inst to inst_list do linking - add one FuncInst to another's predecessors and successors
+ */
+void FuncNode::update_inst_tree(action_list_t * act_list)
{
- ASSERT(inst);
- if ( !inst->is_read() )
+ if (act_list == NULL)
+ return;
+ else if (act_list->size() == 0)
return;
- void * location = inst->get_location();
+ /* build inst_list from act_list for later processing */
+ func_inst_list_t inst_list;
+ for (sllnode<ModelAction *> * it = act_list->begin(); it != NULL; it = it->getNext()) {
+ ModelAction * act = it->getVal();
+ FuncInst * func_inst = get_or_add_inst(act);
- func_inst_list_mt * reads;
- if ( !reads_by_loc.contains(location) ) {
- reads = new func_inst_list_mt();
- reads->push_back(inst);
- reads_by_loc.put(location, reads);
- return;
+ if (func_inst != NULL)
+ inst_list.push_back(func_inst);
}
- reads = reads_by_loc.get(location);
- func_inst_list_mt::iterator it;
- for (it = reads->begin(); it != reads->end(); it++) {
- if (inst == *it)
- return;
+ /* start linking */
+ sllnode<FuncInst *>* it = inst_list.begin();
+ sllnode<FuncInst *>* prev;
+
+ /* add the first instruction to the list of entry insts */
+ FuncInst * entry_inst = it->getVal();
+ add_entry_inst(entry_inst);
+
+ it = it->getNext();
+ while (it != NULL) {
+ prev = it->getPrev();
+
+ FuncInst * prev_inst = prev->getVal();
+ FuncInst * curr_inst = it->getVal();
+
+ prev_inst->add_succ(curr_inst);
+ curr_inst->add_pred(prev_inst);
+
+ it = it->getNext();
}
+}
+
+/* @param tid thread id
+ * Store the values read by atomic read actions into thrd_read_map */
+void FuncNode::store_read(ModelAction * act, uint32_t tid)
+{
+ ASSERT(act);
+
+ void * location = act->get_location();
+ uint64_t read_from_val = act->get_reads_from_value();
+
+ /* resize and initialize */
+ uint32_t old_size = thrd_read_map.size();
+ if (old_size <= tid) {
+ thrd_read_map.resize(tid + 1);
+ for (uint32_t i = old_size; i < tid + 1;i++)
+ thrd_read_map[i] = new read_map_t();
+ }
+
+ read_map_t * read_map = thrd_read_map[tid];
+ read_map->put(location, read_from_val);
+
+ /* Store the memory locations where atomic reads happen */
+ // read_locations.add(location);
+}
+
+uint64_t FuncNode::query_last_read(void * location, uint32_t tid)
+{
+ if (thrd_read_map.size() <= tid)
+ return 0xdeadbeef;
+
+ read_map_t * read_map = thrd_read_map[tid];
+
+ /* last read value not found */
+ if ( !read_map->contains(location) )
+ return 0xdeadbeef;
+
+ uint64_t read_val = read_map->get(location);
+ return read_val;
+}
+
+/* @param tid thread id
+ * Reset read map for a thread. This function shall only be called
+ * when a thread exits a function
+ */
+void FuncNode::clear_read_map(uint32_t tid)
+{
+ if (thrd_read_map.size() <= tid)
+ return;
- reads->push_back(inst);
+ thrd_read_map[tid]->reset();
+}
+
+void FuncNode::init_predicate_tree(func_inst_list_t * inst_list)
+{
+ if (inst_list == NULL || inst_list->size() == 0)
+ return;
+
+ if (predicate_tree_initialized)
+ return;
+
+ predicate_tree_initialized = true;
+
+ // maybe restrict the size of hashtable to save calloc time
+ HashTable<void *, FuncInst *, uintptr_t, 4> loc_inst_map;
+
+ sllnode<FuncInst *> *it = inst_list->begin();
+ sllnode<FuncInst *> *prev;
+
+ FuncInst * entry_inst = it->getVal();
+
+ /* entry instruction has no predicate expression */
+ Predicate * pred_entry = new Predicate(entry_inst);
+ loc_inst_map.put(entry_inst->get_location(), entry_inst);
+
+ it = it->getNext();
+ while (it != NULL) {
+ prev = it->getPrev();
+
+ FuncInst * curr_inst = it->getVal();
+ FuncInst * prev_inst = prev->getVal();
+
+ if ( loc_inst_map.contains(curr_inst->get_location()) ) {
+ Predicate * pred1 = new Predicate(curr_inst);
+ pred1->add_predicate(EQUALITY, curr_inst->get_location(), 0);
+
+ Predicate * pred2 = new Predicate(curr_inst);
+ pred2->add_predicate(EQUALITY, curr_inst->get_location(), 1);
+ }
+
+ loc_inst_map.put(curr_inst->get_location(), curr_inst);
+
+ it = it->getNext();
+ }
+}
+
+
+void FuncNode::generate_predicate(FuncInst *func_inst)
+{
+
+}
+
+/* @param tid thread id
+ * Print the values read by the last read actions for each memory location
+ */
+void FuncNode::print_last_read(uint32_t tid)
+{
+ ASSERT(thrd_read_map.size() > tid);
+ read_map_t * read_map = thrd_read_map[tid];
+/*
+ mllnode<void *> * it;
+ for (it = read_locations.begin();it != NULL;it=it->getNext()) {
+ if ( !read_map->contains(it->getVal()) )
+ break;
+
+ uint64_t read_val = read_map->get(it->getVal());
+ model_print("last read of thread %d at %p: 0x%x\n", tid, it->getVal(), read_val);
+ }
+*/
}