resources releasing; metrics

[ROCm/rocprofiler commit: 79510b8c6c]
This commit is contained in:
Evgeny
2018-02-01 14:52:21 -06:00
rodzic 14e45e9cb4
commit 80d462a8c2
17 zmienionych plików z 789 dodań i 238 usunięć
+1 -1
Wyświetl plik
@@ -200,7 +200,7 @@ class Context {
const rocprofiler_feature_kind_t kind = info->kind;
const char* name = info->name;
if (kind != ROCPROFILER_FEATURE_KIND_TRACE) { // Processing metrics features
if (kind == ROCPROFILER_FEATURE_KIND_METRIC) { // Processing metrics features
const Metric* metric = metrics_->Get(name);
if (metric == NULL)
EXC_RAISING(HSA_STATUS_ERROR, "input metric '" << name << "' is not found");
+109 -34
Wyświetl plik
@@ -38,7 +38,7 @@ class Metric {
virtual const xml::Expr* GetExpr() const = 0;
private:
std::string name_;
const std::string name_;
};
class BaseMetric : public Metric {
@@ -107,10 +107,38 @@ class MetricsDict {
}
}
const Metric* Get(const std::string& name) const {
const Metric* Get(const std::string& name) {
const Metric* metric = NULL;
auto it = cache_.find(name);
if (it != cache_.end()) metric = it->second;
else {
const std::size_t pos = name.find(':');
if (pos != std::string::npos) {
std::string block_name = name.substr(0, pos);
const std::string event_str = name.substr(pos + 1);
uint32_t block_index = 0;
bool indexed = false;
const std::size_t pos1 = block_name.find('[');
if (pos1 != std::string::npos) {
const std::size_t pos2 = block_name.find(']');
if (pos2 == std::string::npos) EXC_RAISING(HSA_STATUS_ERROR, "Malformed metric name '" << name << "'");
block_name = name.substr(0, pos1);
const std::string block_index_str = name.substr(pos1 + 1, pos2 - (pos1 + 1));
block_index = atol(block_index_str.c_str());
indexed = true;
}
const hsa_ven_amd_aqlprofile_id_query_t query = Translate(agent_info_, block_name);
const hsa_ven_amd_aqlprofile_block_name_t block_id = (hsa_ven_amd_aqlprofile_block_name_t)query.id;
if ((query.instance_count > 1) && (indexed == false)) EXC_RAISING(HSA_STATUS_ERROR, "Malformed indexed metric name '" << name << "'");
const uint32_t event_id = atol(event_str.c_str());
const counter_t counter = {name, {block_id, block_index, event_id}};
metric = new BaseMetric(name, counter);
}
}
return metric;
}
@@ -119,12 +147,15 @@ class MetricsDict {
const_iterator_t End() const { return cache_.end(); }
private:
MetricsDict(const util::AgentInfo* agent_info) : xml_(NULL) {
MetricsDict(const util::AgentInfo* agent_info) : xml_(NULL), agent_info_(agent_info) {
const char* xml_name = getenv("ROCP_METRICS");
if (xml_name != NULL) {
xml_ = xml::Xml::Create(xml_name);
if (xml_ == NULL) EXC_RAISING(HSA_STATUS_ERROR, "metrics .xml open error '" << xml_name << "'");
std::cout << "ROCProfiler: importing metrics from '" << xml_name << "':" << std::endl;
xml_->AddConst("top.const.metric", "NUM_SIMDS", 64);
xml_->AddConst("top.const.metric", "NUM_SHADER_ENGINES", 4);
std::cout << "ROCProfiler: importing '" << xml_name << "':" << std::endl;
ImportMetrics(agent_info, "const");
ImportMetrics(agent_info, agent_info->gfxip);
ImportMetrics(agent_info, "global");
}
@@ -135,47 +166,53 @@ class MetricsDict {
for (auto& entry : cache_) delete entry.second;
}
void ImportMetrics(const util::AgentInfo* agent_info, const char* scope) {
auto scope_list = xml_->GetNodes("top." + std::string(scope) + ".metric");
static hsa_ven_amd_aqlprofile_id_query_t Translate(const util::AgentInfo* agent_info, const std::string& block_name) {
hsa_ven_amd_aqlprofile_profile_t profile;
profile.agent = agent_info->dev_id;
hsa_ven_amd_aqlprofile_id_query_t query = {block_name.c_str(), 0, 0};
hsa_status_t status =
util::HsaRsrcFactory::Instance().AqlProfileApi()->hsa_ven_amd_aqlprofile_get_info(
&profile, HSA_VEN_AMD_AQLPROFILE_INFO_BLOCK_ID, &query);
if (status != HSA_STATUS_SUCCESS) AQL_EXC_RAISING(HSA_STATUS_ERROR, "ImportMetrics: bad block name '" << block_name << "'");
return query;
}
void ImportMetrics(const util::AgentInfo* agent_info, const std::string& scope) {
auto scope_list = xml_->GetNodes("top." + scope + ".metric");
if (!scope_list.empty()) {
std::cout << " " << scope_list.size() << " " << scope << " metrics found" << std::endl;
for (auto node : scope_list) {
const std::string name = node->opts["name"];
if (cache_.find(name) != cache_.end())
EXC_RAISING(HSA_STATUS_ERROR, "ImportMetrics: metrics redefined '" << name << "'");
const std::string expr_str = node->opts["expr"];
std::string descr = node->opts["descr"];
if (descr.empty()) descr = (expr_str.empty()) ? name : expr_str;
if (expr_str.empty()) {
const std::string block_name = node->opts["block"];
const uint32_t event_id = atoi(node->opts["event"].c_str());
const std::string event_str = node->opts["event"];
const uint32_t event_id = atol(event_str.c_str());
hsa_ven_amd_aqlprofile_profile_t profile;
profile.agent = agent_info->dev_id;
hsa_ven_amd_aqlprofile_id_query_t query = {block_name.c_str(), 0, 0};
hsa_status_t status =
util::HsaRsrcFactory::Instance().AqlProfileApi()->hsa_ven_amd_aqlprofile_get_info(
&profile, HSA_VEN_AMD_AQLPROFILE_INFO_BLOCK_ID, &query);
if (status == HSA_STATUS_SUCCESS) {
const hsa_ven_amd_aqlprofile_block_name_t block_id =
(hsa_ven_amd_aqlprofile_block_name_t)query.id;
if (query.instance_count > 1) {
for (unsigned block_index = 0; block_index < query.instance_count; ++block_index) {
std::ostringstream os;
os << name << '[' << block_index << ']';
const std::string full_name = os.str();
const counter_t counter = {full_name, {block_id, block_index, event_id}};
cache_[full_name] = new BaseMetric(full_name, counter);
}
} else {
const counter_t counter = {name, {block_id, 0, event_id}};
cache_[name] = new BaseMetric(name, counter);
const hsa_ven_amd_aqlprofile_id_query_t query = Translate(agent_info, block_name);
const hsa_ven_amd_aqlprofile_block_name_t block_id = (hsa_ven_amd_aqlprofile_block_name_t)query.id;
if (query.instance_count > 1) {
for (unsigned block_index = 0; block_index < query.instance_count; ++block_index) {
std::ostringstream full_name;
full_name << name << '[' << block_index << ']';
std::ostringstream alias;
alias << block_name << "[" << block_index << "]:" << event_str;
const counter_t counter = {full_name.str(), {block_id, block_index, event_id}};
AddMetric(full_name.str(), alias.str(), counter);
}
} else
AQL_EXC_RAISING(HSA_STATUS_ERROR, "ImportMetrics: bad block name '" << block_name
<< "'");
} else {
const std::string alias = block_name + ":" + event_str;
const counter_t counter = {name, {block_id, 0, event_id}};
AddMetric(name, alias, counter);
}
} else {
xml::Expr* expr_obj = new xml::Expr(expr_str, new ExprCache(&cache_));
std::cout << "# " << descr << std::endl;
std::cout << name << "=" << expr_obj->String() << "\n" << std::endl;
counters_vec_t counters_vec;
for (const std::string var : expr_obj->GetVars()) {
auto it = cache_.find(var);
@@ -184,12 +221,46 @@ class MetricsDict {
<< "' is not found");
it->second->GetCounters(counters_vec);
}
cache_[name] = new ExprMetric(name, counters_vec, expr_obj);
AddMetric(name, counters_vec, expr_obj);
}
}
}
}
const Metric* AddMetric(const std::string& name, const std::string& /*alias*/, const counter_t& counter) {
const Metric* metric = NULL;
const auto ret = cache_.insert({name, NULL});
if (ret.second) {
metric = new BaseMetric(name, counter);
ret.first->second = metric;
} else EXC_RAISING(HSA_STATUS_ERROR, "metric redefined '" << name << "'");
#if 0
if (alias != name) {
if (cache_.find(alias) != cache_.end()) EXC_RAISING(HSA_STATUS_ERROR, "metric alias/name interference '" << alias << "'");
const auto ret = aliases_.insert({alias, name});
if (!ret.second) EXC_RAISING(HSA_STATUS_ERROR, "metric alias redefined '" << alias << "'");
}
#endif
return metric;
}
const Metric* AddMetric(const std::string& name, const counters_vec_t& counters_vec, const xml::Expr* expr_obj) {
const Metric* metric = NULL;
const auto ret = cache_.insert({name, NULL});
if (ret.second) {
metric = new ExprMetric(name, counters_vec, expr_obj);
ret.first->second = metric;
} else EXC_RAISING(HSA_STATUS_ERROR, "expr-metric redefined '" << name << "'");
return metric;
}
#if 0
std::string UnAlias(const std::string& name) const {
auto it = aliases_.find(name);
return (it != aliases_.end()) ? it->second : name;
}
#endif
void Print() {
for (auto& v : cache_) {
const Metric* metric = v.second;
@@ -203,7 +274,11 @@ class MetricsDict {
}
xml::Xml* xml_;
const util::AgentInfo* agent_info_;
cache_t cache_;
#if 0
std::map<std::string, std::string> aliases_;
#endif
static map_t* map_;
static mutex_t mutex_;
+7 -6
Wyświetl plik
@@ -79,15 +79,16 @@ class Profile {
Profile(const util::AgentInfo* agent_info) : agent_info_(agent_info) {
profile_ = {};
profile_.agent = agent_info->dev_id;
completion_signal_ = {};
is_legacy_ = (strncmp(agent_info->name, "gfx8", 4) == 0);
}
virtual ~Profile() {
if (!info_vector_.empty()) {
info_vector_.clear();
hsa_memory_free(profile_.command_buffer.ptr);
hsa_memory_free(profile_.output_buffer.ptr);
free(const_cast<event_t*>(profile_.events));
free(const_cast<parameter_t*>(profile_.parameters));
info_vector_.clear();
if (profile_.command_buffer.ptr) hsa_memory_free(profile_.command_buffer.ptr);
if (profile_.output_buffer.ptr) hsa_memory_free(profile_.output_buffer.ptr);
if (profile_.events) free(const_cast<event_t*>(profile_.events));
if (profile_.parameters) free(const_cast<parameter_t*>(profile_.parameters));
if (completion_signal_.handle) {
hsa_status_t status = hsa_signal_destroy(completion_signal_);
if (status != HSA_STATUS_SUCCESS) EXC_RAISING(status, "signal_destroy " << std::hex << status);
}
@@ -26,12 +26,14 @@ POSSIBILITY OF SUCH DAMAGE.
#include <dlfcn.h>
#include <hsa.h>
#include <hsa_ext_amd.h>
#include <hsa_ext_finalize.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <atomic>
#include <cassert>
#include <fstream>
#include <iostream>
@@ -76,6 +78,7 @@ hsa_status_t HsaRsrcFactory::FindMemRegionsCallback(hsa_region_t region, void* d
// Constructor of the class
HsaRsrcFactory::HsaRsrcFactory() {
// Initialize the Hsa Runtime
printf("HSA init\n");
hsa_status_t status = hsa_init();
CHECK_STATUS("Error in hsa_init", status);
@@ -100,6 +103,10 @@ HsaRsrcFactory::HsaRsrcFactory() {
// Destructor of the class
HsaRsrcFactory::~HsaRsrcFactory() {
for (auto p : cpu_list_) free(const_cast<AgentInfo*>(p));
for (auto p : gpu_list_) free(const_cast<AgentInfo*>(p));
printf("HSA shutdown\n");
hsa_status_t status = hsa_shut_down();
CHECK_STATUS("Error in hsa_shut_down", status);
}
@@ -162,12 +169,15 @@ const AgentInfo* HsaRsrcFactory::AddAgentInfo(const hsa_agent_t agent) {
hsa_agent_get_info(agent, HSA_AGENT_INFO_NAME, agent_info->name);
strncpy(agent_info->gfxip, agent_info->name, 4);
agent_info->gfxip[4] = '\0';
agent_info->max_wave_size = 0;
hsa_agent_get_info(agent, HSA_AGENT_INFO_WAVEFRONT_SIZE, &agent_info->max_wave_size);
agent_info->max_queue_size = 0;
hsa_agent_get_info(agent, HSA_AGENT_INFO_QUEUE_MAX_SIZE, &agent_info->max_queue_size);
agent_info->profile = hsa_profile_t(108);
hsa_agent_get_info(agent, HSA_AGENT_INFO_PROFILE, &agent_info->profile);
agent_info->is_apu = (agent_info->profile == HSA_PROFILE_FULL) ? true : false;
hsa_agent_get_info(agent, static_cast<hsa_agent_info_t>(HSA_AMD_AGENT_INFO_COMPUTE_UNIT_COUNT), &agent_info->cu_num);
hsa_agent_get_info(agent, static_cast<hsa_agent_info_t>(HSA_AMD_AGENT_INFO_MAX_WAVES_PER_CU), &agent_info->waves_per_cu);
hsa_agent_get_info(agent, static_cast<hsa_agent_info_t>(HSA_AMD_AGENT_INFO_NUM_SIMDS_PER_CU), &agent_info->simds_per_cu);
hsa_agent_get_info(agent, static_cast<hsa_agent_info_t>(HSA_AMD_AGENT_INFO_NUM_SHADER_ENGINES), &agent_info->se_num);
hsa_agent_get_info(agent, static_cast<hsa_agent_info_t>(HSA_AMD_AGENT_INFO_NUM_SHADER_ARRAYS_PER_SE), &agent_info->shader_arrays_per_se);
// Initialize memory regions to zero
agent_info->kernarg_region.handle = 0;
@@ -349,8 +359,8 @@ bool HsaRsrcFactory::TransferData(void* dest_buff, void* src_buff, uint32_t leng
//
// @return bool true if successful, false otherwise
//
bool HsaRsrcFactory::LoadAndFinalize(const AgentInfo* agent_info, const char* brig_path,
char* kernel_name, hsa_executable_symbol_t* code_desc) {
void* HsaRsrcFactory::LoadAndFinalize(const AgentInfo* agent_info, const char* brig_path,
const char* kernel_name, hsa_executable_t* hsa_exec, hsa_executable_symbol_t* code_desc) {
// Finalize the Hsail object into code object
hsa_status_t status;
hsa_code_object_t code_object;
@@ -364,52 +374,52 @@ bool HsaRsrcFactory::LoadAndFinalize(const AgentInfo* agent_info, const char* br
if (!codeStream) {
std::cerr << "Error: failed to load " << filename << std::endl;
assert(false);
return false;
return NULL;
}
// Allocate memory to read in code object from file
size_t size = std::string::size_type(codeStream.tellg());
char* codeBuff = (char*)AllocateSysMemory(agent_info, size);
if (!codeBuff) {
char* code_buf = (char*)AllocateSysMemory(agent_info, size);
if (!code_buf) {
std::cerr << "Error: failed to allocate memory for code object." << std::endl;
assert(false);
return false;
return NULL;
}
// Read the code object into allocated memory
codeStream.seekg(0, std::ios::beg);
std::copy(std::istreambuf_iterator<char>(codeStream), std::istreambuf_iterator<char>(), codeBuff);
std::copy(std::istreambuf_iterator<char>(codeStream), std::istreambuf_iterator<char>(), code_buf);
// De-Serialize the code object that has been read into memory
status = hsa_code_object_deserialize(codeBuff, size, NULL, &code_object);
status = hsa_code_object_deserialize(code_buf, size, NULL, &code_object);
if (status != HSA_STATUS_SUCCESS) {
std::cerr << "Failed to deserialize code object" << std::endl;
return false;
if (code_buf) hsa_memory_free(code_buf);
return NULL;
}
// Create executable.
hsa_executable_t hsaExecutable;
status =
hsa_executable_create(HSA_PROFILE_FULL, HSA_EXECUTABLE_STATE_UNFROZEN, "", &hsaExecutable);
hsa_executable_create(HSA_PROFILE_FULL, HSA_EXECUTABLE_STATE_UNFROZEN, "", hsa_exec);
CHECK_STATUS("Error in creating executable object", status);
// Load code object.
status = hsa_executable_load_code_object(hsaExecutable, agent_info->dev_id, code_object, "");
status = hsa_executable_load_code_object(*hsa_exec, agent_info->dev_id, code_object, "");
CHECK_STATUS("Error in loading executable object", status);
// Freeze executable.
status = hsa_executable_freeze(hsaExecutable, "");
status = hsa_executable_freeze(*hsa_exec, "");
CHECK_STATUS("Error in freezing executable object", status);
// Get symbol handle.
hsa_executable_symbol_t kernelSymbol;
status = hsa_executable_get_symbol(hsaExecutable, NULL, kernel_name, agent_info->dev_id, 0,
status = hsa_executable_get_symbol(*hsa_exec, NULL, kernel_name, agent_info->dev_id, 0,
&kernelSymbol);
CHECK_STATUS("Error in looking up kernel symbol", status);
// Update output parameter
*code_desc = kernelSymbol;
return true;
return code_buf;
}
// Print the various fields of Hsa Gpu Agents
@@ -423,13 +433,47 @@ bool HsaRsrcFactory::PrintGpuAgents(const std::string& header) {
std::clog << "> agent[" << idx << "] :" << std::endl;
std::clog << ">> Name : " << agent_info->name << std::endl;
std::clog << ">> APU : " << agent_info->is_apu << std::endl;
std::clog << ">> HSAIL profile : " << agent_info->profile << std::endl;
std::clog << ">> Max Wave Size : " << agent_info->max_wave_size << std::endl;
std::clog << ">> Max Queue Size : " << agent_info->max_queue_size << std::endl;
std::clog << ">> Kernarg Region Id : " << agent_info->coarse_region.handle << std::endl;
std::clog << ">> CU number : " << agent_info->cu_num << std::endl;
std::clog << ">> Waves per CU : " << agent_info->waves_per_cu << std::endl;
std::clog << ">> SIMDs per CU : " << agent_info->simds_per_cu << std::endl;
std::clog << ">> SE number : " << agent_info->se_num << std::endl;
std::clog << ">> Shader Arrays per SE : " << agent_info->shader_arrays_per_se << std::endl;
}
return true;
}
uint64_t HsaRsrcFactory::Submit(hsa_queue_t* queue, void* packet) {
const uint32_t slot_size_b = 0x40;
// adevance command queue
const uint64_t write_idx = hsa_queue_load_write_index_relaxed(queue);
hsa_queue_store_write_index_relaxed(queue, write_idx + 1);
while ((write_idx - hsa_queue_load_read_index_relaxed(queue)) >= queue->size) {
sched_yield();
}
uint32_t slot_idx = (uint32_t)(write_idx % queue->size);
uint32_t* queue_slot = (uint32_t*)((uintptr_t)(queue->base_address) + (slot_idx * slot_size_b));
uint32_t* slot_data = (uint32_t*)packet;
// Copy buffered commands into the queue slot.
// Overwrite the AQL invalid header (first dword) last.
// This prevents the slot from being read until it's fully written.
memcpy(&queue_slot[1], &slot_data[1], slot_size_b - sizeof(uint32_t));
std::atomic<uint32_t>* header_atomic_ptr = reinterpret_cast<std::atomic<uint32_t>*>(&queue_slot[0]);
header_atomic_ptr->store(slot_data[0], std::memory_order_release);
// ringdoor bell
hsa_signal_store_relaxed(queue->doorbell_signal, write_idx);
return write_idx;
}
HsaRsrcFactory* HsaRsrcFactory::instance_ = NULL;
HsaRsrcFactory::mutex_t HsaRsrcFactory::mutex_;
@@ -67,6 +67,9 @@ struct AgentInfo {
// Agent type - Cpu = 0, Gpu = 1 or Dsp = 2
uint32_t dev_type;
// APU flag
bool is_apu;
// Agent system index
uint32_t dev_index;
@@ -90,6 +93,21 @@ struct AgentInfo {
// Memory region supporting kernel arguments
hsa_region_t kernarg_region;
// The number of compute unit available in the agent.
uint32_t cu_num;
// Maximum number of waves possible in a Compute Unit.
uint32_t waves_per_cu;
// Number of SIMD's per compute unit CU
uint32_t simds_per_cu;
// Number of Shader Engines (SE) in Gpu
uint32_t se_num;
// Number of Shader Arrays Per Shader Engines in Gpu
uint32_t shader_arrays_per_se;
};
class HsaRsrcFactory {
@@ -213,14 +231,17 @@ class HsaRsrcFactory {
// @param code_desc Handle of finalized Code Descriptor that could
// be used to submit for execution
//
// @return bool true if successful, false otherwise
// @return code buffer, non NULL if successful, NULL otherwise
//
bool LoadAndFinalize(const AgentInfo* agent_info, const char* brig_path, char* kernel_name,
hsa_executable_symbol_t* code_desc);
void* LoadAndFinalize(const AgentInfo* agent_info, const char* brig_path, const char* kernel_name,
hsa_executable_t* hsa_exec, hsa_executable_symbol_t* code_desc);
// Print the various fields of Hsa Gpu Agents
bool PrintGpuAgents(const std::string& header);
// Submit AQL packet to given queue
static uint64_t Submit(hsa_queue_t* queue, void* packet);
// Return AqlProfile API table
typedef hsa_ven_amd_aqlprofile_1_00_pfn_t aqlprofile_pfn_t;
const aqlprofile_pfn_t* AqlProfileApi() const { return &aqlprofile_api_; }
+106 -1
Wyświetl plik
@@ -24,6 +24,7 @@ class div_zero_exception_t : public exception_t {
};
typedef uint64_t args_t;
static const args_t ARGS_MAX = UINT64_MAX;
typedef std::map<std::string, args_t> args_map_t;
class Expr;
@@ -177,14 +178,19 @@ class Expr {
bool SubCheck() const { return (sub_count_ == 0); }
unsigned FindOp() const {
unsigned i = pos_;
unsigned open_n = 0;
while (i < expr_.length()) {
switch (Symb(i)) {
case '*':
case '/':
case '+':
case '-':
goto end;
case '(':
++open_n;
break;
case ')':
if (open_n != 0) i += 1;
goto end;
}
++i;
@@ -263,6 +269,74 @@ class var_expr_t : public bin_expr_t {
const std::string name_;
};
class fun_expr_t : public bin_expr_t {
public:
typedef std::vector<var_expr_t> vvect_t;
fun_expr_t(const std::string& fname, const std::string& vname, const uint32_t& vnum) : fname_(fname) {
for (uint32_t i = 0; i < vnum; ++i) {
std::ostringstream var_full_name;
var_full_name << vname << "[" << i << "]";
vvect.push_back(var_expr_t(var_full_name.str()));
}
}
const vvect_t& GetVars() const { return vvect; }
std::string Symbol() const {
const std::string var = vvect[0].Symbol();
const std::string vname = var.substr(0, var.length() - 3);
std::ostringstream oss;
std::string str("(");
str.back() = ')';
oss << fname_ << "(" << vname << "," << vvect.size() << ")";
return oss.str();
}
private:
const std::string fname_;
vvect_t vvect;
};
class sum_expr_t : public fun_expr_t {
public:
sum_expr_t(const std::string& vname, const uint32_t& vnum) : fun_expr_t("sum", vname, vnum) {}
args_t Eval(const args_cache_t& args) const {
args_t result = 0;
for (const auto& var : GetVars()) result += var.Eval(args);
return result;
}
};
class avr_expr_t : public fun_expr_t {
public:
avr_expr_t(const std::string& vname, const uint32_t& vnum) : fun_expr_t("avr", vname, vnum) {}
args_t Eval(const args_cache_t& args) const {
args_t result = 0;
for (const auto& var : GetVars()) result += var.Eval(args);
return result / GetVars().size();
}
};
class min_expr_t : public fun_expr_t {
public:
min_expr_t(const std::string& vname, const uint32_t& vnum) : fun_expr_t("min", vname, vnum) {}
args_t Eval(const args_cache_t& args) const {
args_t result = ARGS_MAX;
for (const auto& var : GetVars()) {
args_t val = var.Eval(args);
result = (val < result) ? val : result;
}
return result;
}
};
class max_expr_t : public fun_expr_t {
public:
max_expr_t(const std::string& vname, const uint32_t& vnum) : fun_expr_t("max", vname, vnum) {}
args_t Eval(const args_cache_t& args) const {
args_t result = 0;
for (const auto& var : GetVars()) {
args_t val = var.Eval(args);
result = (val > result) ? val : result;
}
return result;
}
};
inline const bin_expr_t* bin_expr_t::CreateExpr(const bin_expr_t* arg1, const bin_expr_t* arg2,
const char op) {
const bin_expr_t* expr = NULL;
@@ -285,11 +359,41 @@ inline const bin_expr_t* bin_expr_t::CreateExpr(const bin_expr_t* arg1, const bi
inline const bin_expr_t* bin_expr_t::CreateArg(Expr* obj, const std::string str) {
const bin_expr_t* arg = NULL;
const unsigned i = strspn(str.c_str(), "1234567890");
if (i == str.length()) {
const unsigned value = atoi(str.c_str());
arg = new const_expr_t(value);
} else {
}
if (arg == NULL) {
const std::size_t pos = str.find('(');
if (pos != std::string::npos) {
char* fname = NULL;
char* vname = NULL;
int vnum = 0;
int ret = sscanf(str.c_str(), "%m[a-zA-Z_](%m[0-9a-zA-Z_],%d)", &fname, &vname, &vnum);
if (ret == 3) {
const std::string fun_name(fname);
const fun_expr_t* farg = NULL;
if (fun_name == "sum") {
farg = new sum_expr_t(vname, vnum);
} else if (fun_name == "avr") {
farg = new avr_expr_t(vname, vnum);
} else if (fun_name == "min") {
farg = new min_expr_t(vname, vnum);
} else if (fun_name == "max") {
farg = new max_expr_t(vname, vnum);
}
if (farg) for (const auto& var : farg->GetVars()) obj->AddVar(var.Symbol());
arg = farg;
}
free(fname);
free(vname);
}
}
if (arg == NULL) {
const std::string sub_expr = obj->Lookup(str);
if (sub_expr.empty()) {
arg = new var_expr_t(str);
@@ -299,6 +403,7 @@ inline const bin_expr_t* bin_expr_t::CreateArg(Expr* obj, const std::string str)
arg = expr->GetTree();
}
}
return arg;
}
+63 -8
Wyświetl plik
@@ -36,11 +36,29 @@ class Xml {
return xml;
}
void AddExpr(const std::string& full_tag, const std::string& name, const std::string& expr) {
const std::size_t pos = full_tag.rfind('.');
const std::size_t pos1 = (pos == std::string::npos) ? 0 : pos + 1;
const std::string level_tag = full_tag.substr(pos1);
level_t* level = new level_t;
map_[full_tag].push_back(level);
level->tag = level_tag;
level->opts["name"] = name;
level->opts["expr"] = expr;
}
void AddConst(const std::string& full_tag, const std::string& name, const uint64_t& val) {
std::ostringstream oss;
oss << val;
AddExpr(full_tag, name, oss.str());
}
static void Destroy(Xml *xml) { delete xml; }
std::vector<level_t*> GetNodes(std::string global_tag) { return map_[global_tag]; }
void Print() const {
std::cout << "XML file '" << file_name_ << "':" << std::endl;
for (auto& elem : map_) {
for (auto node : elem.second) {
if (node->opts.size()) {
@@ -74,13 +92,14 @@ class Xml {
while (1) {
token_t token = (remainder.size()) ? remainder : NextToken();
remainder.clear();
// token_t token1 = token;
// token1.push_back('\0');
// std::cout << "> " << &token1[0] << std::endl;
// End of file
if (token.size() == 0) break;
// token_t token1 = token;
// token1.push_back('\0');
// std::cout << "> " << &token1[0] << std::endl;
switch (state_) {
case BODY_STATE:
if (token[0] == '<') {
@@ -146,6 +165,11 @@ class Xml {
~Xml() {}
bool SpaceCheck() const {
bool cond = ((buffer_[index_] == ' ') || (buffer_[index_] == ' '));
return cond;
}
bool LineEndCheck() {
bool found = false;
if (buffer_[index_] == '\n') {
@@ -162,24 +186,55 @@ class Xml {
token_t NextToken() {
token_t token;
bool in_string = false;
bool special_symb = false;
while (1) {
if (data_size_ == 0) {
data_size_ = read(fd_, buffer_, buf_size_);
if (data_size_ <= 0) break;
}
if (token.empty())
while ((index_ < data_size_) && ((buffer_[index_] == ' ') || LineEndCheck())) {
while ((index_ < data_size_) && (SpaceCheck() || LineEndCheck())) {
++index_;
}
while ((index_ < data_size_) && (buffer_[index_] != ' ') && !LineEndCheck()) {
token.push_back(buffer_[index_++]);
while ((index_ < data_size_) && (in_string || !(SpaceCheck() || LineEndCheck()))) {
const char symb = buffer_[index_];
bool skip_symb = false;
switch (symb) {
case '\\':
if (special_symb) special_symb = false;
else {
special_symb = true;
skip_symb = true;
}
break;
case '"':
if (special_symb) special_symb = false;
else {
in_string = !in_string;
if (!in_string) {
buffer_[index_] = ' ';
--index_;
}
skip_symb = true;
}
break;
}
if (!skip_symb) token.push_back(symb);
++index_;
}
if (index_ == data_size_) {
index_ = 0;
data_size_ = 0;
} else
} else {
if (special_symb || in_string) BadFormat(token);
break;
}
}
return token;