<commit_before>#include "writer/verilog/task.h"

#include "design/design_util.h"
#include "iroha/i_design.h"
#include "iroha/resource_class.h"
#include "writer/connection.h"
#include "writer/module_template.h"
#include "writer/verilog/insn_writer.h"
#include "writer/verilog/module.h"
#include "writer/verilog/ports.h"
#include "writer/verilog/state.h"
#include "writer/verilog/table.h"

namespace iroha {
namespace writer {
namespace verilog {

const int Task::kTaskEntryStateId = -1;

Task::Task(const IResource &res, const Table &table)
  : Resource(res, table) {
}

bool Task::IsTask(const Table &table) {
  ITable *i_table = table.GetITable();
  IInsn *task_entry_insn = DesignUtil::FindTaskEntryInsn(i_table);
  if (task_entry_insn != nullptr) {
    if (resource::IsTask(*(task_entry_insn->GetResource()->GetClass()))) {
      return true;
    }
  }
  return false;
}

string Task::TaskEnablePin(const ITable &tab, const ITable *caller) {
  return TaskPinPrefix(tab, caller) + "_en";
}

string Task::TaskAckPin(const ITable &tab, const ITable *caller) {
  return TaskPinPrefix(tab, caller) + "_ack";
}

string Task::TaskPinPrefix(const ITable &tab, const ITable *caller) {
  string s = "task_" + Util::Itoa(tab.GetId());
  if (caller != nullptr) {
    IModule *caller_mod = caller->GetModule();
    s += "_" + Util::Itoa(caller_mod->GetId()) +
      "_" + Util::Itoa(caller->GetId());
  }
  return s;
}

void Task::BuildResource() {
  auto *klass = res_.GetClass();
  if (resource::IsTask(*klass)) {
    BuildTaskResource();
  }
  if (resource::IsTaskCall(*klass)) {
    BuildTaskCallResource();
  }
}

void Task::BuildInsn(IInsn *insn, State *st) {
  auto *klass = res_.GetClass();
  if (resource::IsTaskCall(*klass)) {
    BuildTaskCallInsn(insn, st);
  }
}

void Task::BuildTaskResource() {
  auto &conn = tab_.GetModule()->GetConnection();
  auto *callers = conn.GetTaskCallers(&res_);
  if (callers == nullptr) {
    return;
  }
  vector<string> task_en;
  for (IResource *caller : *callers) {
    BuildCallWire(caller);
    task_en.push_back(TaskEnablePin(*(tab_.GetITable()), caller->GetTable()));
  }
  string w = TaskEnablePin(*(tab_.GetITable()), nullptr);
  ostream &rs = tmpl_->GetStream(kResourceSection);
  rs << "  wire " << w << ";\n";
  rs << "  assign " << w << " = " << Util::Join(task_en, " | ") << ";\n";
  string ack = TaskAckPin(*(tab_.GetITable()), nullptr);
  ostream &fs = tab_.StateOutputSectionStream();
  fs << "      " << ack
     << " <= (" << tab_.StateVariable() << " == `"
     << tab_.StateName(Task::kTaskEntryStateId) << ") && " << w
     << ";\n";
  rs << "  reg " << ack << ";\n";
  ostream &is = tab_.InitialValueSectionStream();
  is << "  " << ack << " <= 0;\n";
  for (IResource *caller : *callers) {
    string a = TaskAckPin(*(tab_.GetITable()), caller->GetTable());
    rs << "  assign " << a << " = " << ack << ";\n";
  }
}

void Task::BuildCallWire(IResource *caller) {
  IModule *callee_module = res_.GetTable()->GetModule();
  IModule *caller_module = caller->GetTable()->GetModule();
  const IModule *common_root = Connection::GetCommonRoot(callee_module,
							 caller_module);
  if (caller_module == common_root) {
    // downward
    for (IModule *imod = callee_module; imod != common_root;
	 imod = imod->GetParentModule()) {
      AddPort(imod, caller, false);
    }
  } else if (callee_module == common_root) {
    // upward
    for (IModule *imod = caller_module; imod != common_root;
	 imod = imod->GetParentModule()) {
      AddPort(imod, caller, true);
    }
    AddWire(common_root, caller);
  } else {
    // downward
    for (IModule *imod = caller_module; imod != common_root;
	 imod = imod->GetParentModule()) {
      AddPort(imod, caller, true);
    }
    // upward<commit_msg>Add arbitration for task call.<commit_after>#include "writer/verilog/task.h"

#include "design/design_util.h"
#include "iroha/i_design.h"
#include "iroha/resource_class.h"
#include "writer/connection.h"
#include "writer/module_template.h"
#include "writer/verilog/insn_writer.h"
#include "writer/verilog/module.h"
#include "writer/verilog/ports.h"
#include "writer/verilog/state.h"
#include "writer/verilog/table.h"

namespace iroha {
namespace writer {
namespace verilog {

const int Task::kTaskEntryStateId = -1;

Task::Task(const IResource &res, const Table &table)
  : Resource(res, table) {
}

bool Task::IsTask(const Table &table) {
  ITable *i_table = table.GetITable();
  IInsn *task_entry_insn = DesignUtil::FindTaskEntryInsn(i_table);
  if (task_entry_insn != nullptr) {
    if (resource::IsTask(*(task_entry_insn->GetResource()->GetClass()))) {
      return true;
    }
  }
  return false;
}

string Task::TaskEnablePin(const ITable &tab, const ITable *caller) {
  return TaskPinPrefix(tab, caller) + "_en";
}

string Task::TaskAckPin(const ITable &tab, const ITable *caller) {
  return TaskPinPrefix(tab, caller) + "_ack";
}

string Task::TaskPinPrefix(const ITable &tab, const ITable *caller) {
  string s = "task_" + Util::Itoa(tab.GetId());
  if (caller != nullptr) {
    IModule *caller_mod = caller->GetModule();
    s += "_" + Util::Itoa(caller_mod->GetId()) +
      "_" + Util::Itoa(caller->GetId());
  }
  return s;
}

void Task::BuildResource() {
  auto *klass = res_.GetClass();
  if (resource::IsTask(*klass)) {
    BuildTaskResource();
  }
  if (resource::IsTaskCall(*klass)) {
    BuildTaskCallResource();
  }
}

void Task::BuildInsn(IInsn *insn, State *st) {
  auto *klass = res_.GetClass();
  if (resource::IsTaskCall(*klass)) {
    BuildTaskCallInsn(insn, st);
  }
}

void Task::BuildTaskResource() {
  auto &conn = tab_.GetModule()->GetConnection();
  auto *callers = conn.GetTaskCallers(&res_);
  if (callers == nullptr) {
    return;
  }
  vector<string> task_en;
  for (IResource *caller : *callers) {
    BuildCallWire(caller);
    task_en.push_back(TaskEnablePin(*(tab_.GetITable()), caller->GetTable()));
  }
  string w = TaskEnablePin(*(tab_.GetITable()), nullptr);
  ostream &rs = tmpl_->GetStream(kResourceSection);
  rs << "  wire " << w << ";\n";
  rs << "  assign " << w << " = " << Util::Join(task_en, " | ") << ";\n";
  string ack = TaskAckPin(*(tab_.GetITable()), nullptr);
  ostream &fs = tab_.StateOutputSectionStream();
  fs << "      " << ack
     << " <= (" << tab_.StateVariable() << " == `"
     << tab_.StateName(Task::kTaskEntryStateId) << ") && " << w
     << ";\n";
  rs << "  reg " << ack << ";\n";
  ostream &is = tab_.InitialValueSectionStream();
  is << "  " << ack << " <= 0;\n";
  string high_en;
  for (IResource *caller : *callers) {
    string a = TaskAckPin(*(tab_.GetITable()), caller->GetTable());
    rs << "  assign " << a << " = ";
    if (!high_en.empty()) {
      // Ack will be asserted only when higher caller is not requesting.
      rs << "!(" << high_en << ") && ";
    }
    rs << ack << ";\n";
    string en = TaskEnablePin(*(tab_.GetITable()), caller->GetTable());
    if (!high_en.empty()) {
      high_en = high_en + " | ";
    }
    high_en += en;
  }
}

void Task::BuildCallWire(IResource *caller) {
  IModule *callee_module = res_.GetTable()->GetModule();
  IModule *caller_module = caller->GetTable()->GetModule();
  const IModule *common_root = Connection::GetCommonRoot(callee_module,
							 caller_module);
  if (caller_module == common_root) {
    // downward
    for (IModule *imod = callee_module; imod != common_root;
	 imod = imod->GetParentModule()) {
      AddPort(imod, caller, false);
    }
  } else if (callee_module == common_root) {
    // upward
    for (IModule *imod = caller_module; imod != common_root;
	 imod = imod->GetParentModule()) {
      AddPort(imod, caller, true);
    }
    AddWire(common_root, caller);
  } else {
    // downward
    for (IModule *imod = caller_module; imod != common_root;
	 imod = imod->GetParentModule()) {
      AddPort(imod, caller, true);
    }
    // upward
{'fraction_non_alphanumeric': 0.17834394904458598, 'fraction_numerical': 0.0005095541401273885, 'mean_word_length': 3.8643122676579926, 'pattern_counts': {'":': 0, '<': 127, '<?xml version=': 0, '>': 36, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '636731', 'n_tokens_mistral': 2824, 'n_tokens_neox': 2803, 'n_words': 551}