diff --git a/example/resnet18_infr.json b/example/resnet18_infr.json new file mode 100644 index 00000000..61045218 --- /dev/null +++ b/example/resnet18_infr.json @@ -0,0 +1,16 @@ +{ + "models": [ + { + "name": "resnet18", + "trace_file": "resnet18.csv", + "onnx_file": "./models/resnet18/resnet18.onnx", + "input_shape": [1, 3, 224, 224], + "num_classes": 1000, + "batch_size": 1, + "scheduler": "simple", + "scheduler_config": { + "max_batch_size": 8 + } + } + ] +} diff --git a/models/resnet18/resnet18.onnx b/models/resnet18/resnet18.onnx index 883731ef..be5077e4 100644 Binary files a/models/resnet18/resnet18.onnx and b/models/resnet18/resnet18.onnx differ diff --git a/scripts/generate_cnn_trace.py b/scripts/generate_cnn_trace.py new file mode 100755 index 00000000..d1a3e0a8 --- /dev/null +++ b/scripts/generate_cnn_trace.py @@ -0,0 +1,24 @@ +import csv +import random + +# Number of trace entries +num_rows = 20 + +# Initialize CSV +with open('./traces/resnet18.csv', 'w', newline='') as csvfile: + writer = csv.writer(csvfile) + writer.writerow(['time', 'prompt_length', 'target_length', 'cached_length']) + + current_time = 0 + for _ in range(num_rows): + # Simulate ResNet18 input + batch_size = random.choice([1, 2, 4, 8]) + input_pixels = 224 * 224 * 3 # total pixels in image + prompt_length = input_pixels * batch_size + target_length = 1000 # number of output classes in ImageNet + cached_length = 0 # ResNet18 usually doesn't use cached states + + writer.writerow([current_time, prompt_length, target_length, cached_length]) + + # Increment time by random interval (simulate requests) + current_time += random.randint(50, 200) # ms diff --git a/src/Common.h b/src/Common.h index 65855be0..c915c1e2 100644 --- a/src/Common.h +++ b/src/Common.h @@ -1,3 +1,4 @@ + #pragma once #include @@ -29,6 +30,8 @@ using json = nlohmann::json; +struct Tensor; + typedef uint64_t addr_type; typedef uint64_t cycle_type; @@ -44,7 +47,8 @@ typedef struct { cycle_type dram_enter_cycle; cycle_type dram_finish_cycle; int buffer_id; -} MemoryAccess; + addr_type tensor_id; // if it doesnt work then id from instruciton should be uint64_t like addr_type so we use uint64_t instead of 32 + } MemoryAccess; enum class Opcode { MOVIN, @@ -72,8 +76,9 @@ typedef struct { Opcode opcode; cycle_type start_cycle; cycle_type finish_cycle; - std::string id; + std::string id; //changes this here since id in instruction.h is uint32_t which is passed by _outputid in global.cc std::vector dependent_ids; + uint32_t tensor_id; std::string dest_id; addr_type dest_addr; uint32_t size; // Used for sram allocation. Multiple of _config.dram_req_size @@ -117,6 +122,7 @@ struct Tile { TileStat stat; std::deque> instructions; + uint32_t tensor_id; //<-- added this bool accum; bool skip; int spad_id; @@ -144,4 +150,4 @@ uint32_t ceil_div(uint32_t src, uint32_t div); std::vector parse_dims(const std::string &str); -std::string dims_to_string(const std::vector &dims); \ No newline at end of file +std::string dims_to_string(const std::vector &dims); diff --git a/src/Core.cc b/src/Core.cc index e624d89b..c208075a 100644 --- a/src/Core.cc +++ b/src/Core.cc @@ -1,9 +1,12 @@ + #include "Core.h" #include "SystolicWS.h" #include "SystolicOS.h" #include "helper/HelperFunctions.h" +struct Tensor; + std::unique_ptr Core::create(uint32_t id, SimulationConfig config) { if (config.core_config[id].core_type == CoreType::SYSTOLIC_WS) { return std::make_unique(id, config); @@ -342,6 +345,7 @@ void Core::handle_ld_inst_queue() { } for (addr_type addr : front->src_addrs) { assert(front->base_addr != GARBEGE_ADDR); + MemoryAccess *access = new MemoryAccess({.id = generate_mem_access_id(), .dram_address = addr + front->base_addr, @@ -351,7 +355,9 @@ void Core::handle_ld_inst_queue() { .request = true, .core_id = _id, .start_cycle = _core_cycle, - .buffer_id = buffer_id}); + .buffer_id = buffer_id, + .tensor_id= front->dest_addr //id is from output_id tensor + }); _request_queue.push(access); } _ld_inst_queue.pop(); @@ -364,7 +370,7 @@ void Core::handle_ld_inst_queue() { void Core::handle_st_inst_queue() { if (!_st_inst_queue.empty()) { std::unique_ptr front = std::move(_st_inst_queue.front()); - if (front->opcode == Opcode::MOVOUT || front->opcode == Opcode::MOVOUT_POOL) { + if (front->opcode == Opcode::MOVOUT || front->opcode == Opcode::MOVOUT_POOL) { Sram *buffer; int buffer_id; if (front->dest_addr >= ACCUM_SPAD_BASE) { @@ -386,7 +392,10 @@ void Core::handle_st_inst_queue() { .request = true, .core_id = _id, .start_cycle = _core_cycle, - .buffer_id = buffer_id}; + .buffer_id = buffer_id, + .tensor_id = front->dest_addr////id is from input_id in tensor + +}; _waiting_write_reqs++; _request_queue.push(access); } diff --git a/src/Instruction.h b/src/Instruction.h index 3b17cba6..4f29b65a 100644 --- a/src/Instruction.h +++ b/src/Instruction.h @@ -25,7 +25,7 @@ class Instruction { enum class Type { LD_INST, ST_INST, EXE_INST }; - uint32_t id; + std::string id; //change Opcode opcode; Type type; size_t tile_size; diff --git a/src/Model.cc b/src/Model.cc index 90edee56..609b5f8d 100644 --- a/src/Model.cc +++ b/src/Model.cc @@ -31,8 +31,9 @@ Model::Model(json model_config, SimulationConfig config, std::string name) } Tensor* Model::get_tensor(uint32_t id) { - return _tensor_map[id].get(); -} + return _tensor_map[id].get(); + } + Tensor* Model::find_tensor(std::string name) { for(auto const& [key, val]: _tensor_map) { @@ -122,19 +123,28 @@ void Model::initialize_model(std::vector>& weight_table) } } - for(auto& [key, val] : _operation_map) { - /* Attention is speacial case */ +for (auto& [key, val] : _operation_map) { + /* Attention is special case */ if (val->get_optype() == "Attention") { - Attention* attention_node = static_cast(val.get()); - attention_node->initialize_onnx_tiles(_mapping_table); - int projection_id = attention_node->_projection_node->get_id(); - _operation_map[projection_id] = std::move(std::unique_ptr(attention_node->_projection_node)); - _operation_map[projection_id]->initialize_tiles(_mapping_table); - } - else { - val->initialize_tiles(_mapping_table); + Attention* attention_node = static_cast(val.get()); + + // ✅ get the output tensor id and make a string version of it + uint32_t tensor_id_str; + if (!attention_node->_outputs.empty()) { + tensor_id_str = attention_node->_outputs.back(); + } + + // ✅ pass it to the specialized initializer + attention_node->initialize_onnx_tiles(_mapping_table, tensor_id_str); + + int projection_id = attention_node->_projection_node->get_id(); + _operation_map[projection_id] = std::move(std::unique_ptr(attention_node->_projection_node)); + _operation_map[projection_id]->initialize_tiles(_mapping_table); + } else { + val->initialize_tiles(_mapping_table); } - } +} + for (auto& [key, val]: _operation_map) { if(val->check_executable()) { @@ -249,4 +259,23 @@ void Model::prepare_regressive() { nr_skip = 0; _start_time = 0; _started = false; -} \ No newline at end of file +} +extern std::unordered_map g_tensor_addr_map; +extern std::mutex g_tensor_map_mutex; + +void Model::tensor_track(uint64_t dram_addr) { + std::lock_guard lock(g_tensor_map_mutex); + + for (auto& [id, info] : g_tensor_addr_map) { + if (dram_addr >= info.start_addr && dram_addr < info.end_addr) { + spdlog::info("DRAM access 0x{:x} → TensorID={} Name={} Range=[0x{:x}-0x{:x}) Size={}", + dram_addr, id, info.name, info.start_addr, info.end_addr, info.size); + return; + } + } + + spdlog::info("DRAM access 0x{:x} → [no matching tensor found]", dram_addr); +} + + + diff --git a/src/Model.h b/src/Model.h index 5df20de4..349ed4f1 100644 --- a/src/Model.h +++ b/src/Model.h @@ -18,7 +18,10 @@ class Model { uint32_t get_root_node_id() { return _root_node_id; } void add_tensor(std::unique_ptr tensor); void set_layer_finish(uint32_t id); - + //added + void tensor_track(uint64_t tensor_id); + +//end std::string get_name() { return _name; } uint32_t executable_layer_size(); Operation* get_executable_tile(); diff --git a/src/SimulationConfig.h b/src/SimulationConfig.h index 51ee13db..c2087f36 100644 --- a/src/SimulationConfig.h +++ b/src/SimulationConfig.h @@ -69,6 +69,8 @@ struct SimulationConfig { uint32_t precision; uint32_t full_precision = 4; std::string layout; +//added this here only +uint32_t vector_process_bit = 256; // added line /* * This map stores the partition information: diff --git a/src/Simulator.cc b/src/Simulator.cc index c8e05900..8bbae1e4 100644 --- a/src/Simulator.cc +++ b/src/Simulator.cc @@ -1,3 +1,4 @@ + #include "Simulator.h" #include @@ -78,132 +79,215 @@ Simulator::Simulator(SimulationConfig config, bool language_mode) std::make_heap(_models.begin(), _models.end(), CompareModel()); } + void Simulator::run_simulator() { spdlog::info("======Start Simulation====="); cycle(); } void Simulator::handle_model() { - if(_language_mode) { - _lang_scheduler->cycle(); - if(_lang_scheduler->can_schedule_model()) { - _models.push_back(_lang_scheduler->pop_model()); - std::push_heap(_models.begin(), _models.end(), CompareModel()); + if (_language_mode) { + _lang_scheduler->cycle(); + if (_lang_scheduler->can_schedule_model()) { + _models.push_back(_lang_scheduler->pop_model()); + std::push_heap(_models.begin(), _models.end(), CompareModel()); + } + } + + while (!_models.empty() && _models.front()->get_request_time() <= _core_time) { + std::unique_ptr launch_model = std::move(_models.front()); + + std::pop_heap(_models.begin(), _models.end(), CompareModel()); + _models.pop_back(); + + launch_model->initialize_model(_weight_table[launch_model->get_name()]); + launch_model->set_request_time(_core_time); + spdlog::info("Schedule model: {} at {} us", launch_model->get_name(), _core_time); + + // --- set active model before handing off to scheduler --- +_active_model_ptr = launch_model.get(); // non-owning pointer for tracking +_active_model = std::move(launch_model); // transfer ownership to simulator + +// schedule the active model (transfer ownership to scheduler) +_scheduler->schedule_model(std::move(_active_model), 1); + } - } - while (!_models.empty() && _models.front()->get_request_time() <= _core_time) { - std::unique_ptr launch_model = std::move(_models.front()); - std::pop_heap(_models.begin(), _models.end(), CompareModel()); - _models.pop_back(); - - launch_model->initialize_model(_weight_table[launch_model->get_name()]); - launch_model->set_request_time(_core_time); - spdlog::info("Schedule model: {} at {} us", launch_model->get_name(), _core_time); - _scheduler->schedule_model(std::move(launch_model), 1); - } } + void Simulator::cycle() { - OpStat op_stat; - ModelStat model_stat; - uint32_t tile_count; - bool is_accum_tile; - while (running()) { - int model_id = 0; - - set_cycle_mask(); - // Core Cycle - if (_cycle_mask & CORE_MASK) { - /* Handle requested model */ - handle_model(); - - for (int core_id = 0; core_id < _n_cores; core_id++) { - std::unique_ptr finished_tile = _cores[core_id]->pop_finished_tile(); - if (finished_tile->status == Tile::Status::FINISH) { - _scheduler->finish_tile(core_id, finished_tile->layer_id); - } - // Issue new tile to core - if (!_scheduler->empty()) { - is_accum_tile = _scheduler->is_accum_tile(core_id, 0); - if (_cores[core_id]->can_issue(is_accum_tile)) { - std::unique_ptr tile = _scheduler->get_tile(core_id); - if (tile->status == Tile::Status::INITIALIZED) { - _cores[core_id]->issue(std::move(tile)); - _tile_timestamp.push_back(std::chrono::high_resolution_clock::now()); + OpStat op_stat; + ModelStat model_stat; + uint32_t tile_count; + bool is_accum_tile; + + while (running()) { + int model_id = 0; + + set_cycle_mask(); + + // --- Core Cycle --- + if (_cycle_mask & CORE_MASK) { + handle_model(); + + for (int core_id = 0; core_id < _n_cores; core_id++) { + std::unique_ptr finished_tile = _cores[core_id]->pop_finished_tile(); + if (finished_tile->status == Tile::Status::FINISH) { + _scheduler->finish_tile(core_id, finished_tile->layer_id); + } + + if (!_scheduler->empty()) { + is_accum_tile = _scheduler->is_accum_tile(core_id, 0); + if (_cores[core_id]->can_issue(is_accum_tile)) { + std::unique_ptr tile = _scheduler->get_tile(core_id); + if (tile->status == Tile::Status::INITIALIZED) { + _cores[core_id]->issue(std::move(tile)); + _tile_timestamp.push_back(std::chrono::high_resolution_clock::now()); + } + } + } + _cores[core_id]->cycle(); } - } + _core_cycles++; } - _cores[core_id]->cycle(); - } - _core_cycles++; - } - // DRAM cycle - if (_cycle_mask & DRAM_MASK) { - _dram->cycle(); - } - // Interconnect cycle - if (_cycle_mask & ICNT_MASK) { - _icnt_cycle++; - - for (int core_id = 0; core_id < _n_cores; core_id++) { - // PUHS core to ICNT. memory request - if (_cores[core_id]->has_memory_request()) { - MemoryAccess *front = _cores[core_id]->top_memory_request(); - front->core_id = core_id; - if (!_icnt->is_full(core_id, front)) { + // --- DRAM Cycle --- + if (_cycle_mask & DRAM_MASK) { + _dram->cycle(); + } + + // --- Interconnect Cycle --- + if (_cycle_mask & ICNT_MASK) { + _icnt_cycle++; + + // --- Core <-> ICNT --- + for (int core_id = 0; core_id < _n_cores; core_id++) { + + // Push core request to ICNT + if (_cores[core_id]->has_memory_request()) { + MemoryAccess* front = _cores[core_id]->top_memory_request(); + front->core_id = core_id; + + if (!_icnt->is_full(core_id, front)) { + _icnt->push(core_id, get_dest_node(front), front); + _cores[core_id]->pop_memory_request(); + _nr_from_core++; + + + } + } + + // Push response from ICNT to core + if (!_icnt->is_empty(core_id)) { + MemoryAccess* resp = _icnt->top(core_id); + _cores[core_id]->push_memory_response(resp); + + + _icnt->pop(core_id); + _nr_to_core++; + } + } + + +// Loop over cores +for (int core_id = 0; core_id < _n_cores; core_id++) { + + // Push core request to ICNT + if (_cores[core_id]->has_memory_request()) { + MemoryAccess* front = _cores[core_id]->top_memory_request(); + front->core_id = core_id; + + // **Log tensor memory request** + + + + if (!_icnt->is_full(core_id, front)) { _icnt->push(core_id, get_dest_node(front), front); _cores[core_id]->pop_memory_request(); + _nr_from_core++; - } - } - // Push response from ICNT. to Core. - if (!_icnt->is_empty(core_id)) { - _cores[core_id]->push_memory_response(_icnt->top(core_id)); - _icnt->pop(core_id); - _nr_to_core++; - } - } - - for (int mem_id = 0; mem_id < _n_memories; mem_id++) { - // ICNT to memory - if (!_icnt->is_empty(_n_cores + mem_id) && - !_dram->is_full(mem_id, _icnt->top(_n_cores + mem_id))) { - _dram->push(mem_id, _icnt->top(_n_cores + mem_id)); - _icnt->pop(_n_cores + mem_id); - _nr_to_mem++; + } - // Pop response to ICNT from dram - if (!_dram->is_empty(mem_id) && - !_icnt->is_full(_n_cores + mem_id, _dram->top(mem_id))) { - _icnt->push(_n_cores + mem_id, get_dest_node(_dram->top(mem_id)), - _dram->top(mem_id)); - _dram->pop(mem_id); - _nr_from_mem++; + } + + // Push response from ICNT to core + if (!_icnt->is_empty(core_id)) { + MemoryAccess* top_access = _icnt->top(core_id); + _cores[core_id]->push_memory_response(top_access); + + _icnt->pop(core_id); + _nr_to_core++; + } +} + +// Loop over memories +for (int mem_id = 0; mem_id < _n_memories; mem_id++) { + + // ICNT -> DRAM + if (!_icnt->is_empty(_n_cores + mem_id) && + !_dram->is_full(mem_id, _icnt->top(_n_cores + mem_id))) { + + MemoryAccess* top_access = _icnt->top(_n_cores + mem_id); +// **Log tensor coming back from DRAM** + spdlog::debug("[DRAM->ICNT] Mem {} sends TensorID {} Size={}", + mem_id, top_access->dram_address, top_access->size); + +if (_active_model_ptr) { + _active_model_ptr->tensor_track(top_access->dram_address); +} + + _dram->push(mem_id, top_access); + + _icnt->pop(_n_cores + mem_id); + _nr_to_mem++; + } + + // DRAM -> ICNT + if (!_dram->is_empty(mem_id) && + !_icnt->is_full(_n_cores + mem_id, _dram->top(mem_id))) { + + MemoryAccess* top_access = _dram->top(mem_id); +// **Log tensor coming back from DRAM** //tensor_id is not passed right + + spdlog::debug("[DRAM->ICNT] Mem {} sends TensorID {} Size={}", + mem_id, top_access->dram_address, top_access->size); + + if (_active_model_ptr) { + _active_model_ptr->tensor_track(top_access->dram_address); +} + + _icnt->push(_n_cores + mem_id, get_dest_node(top_access), top_access); + + _dram->pop(mem_id); + _nr_from_mem++; + } +} + + if (_icnt_interval != 0 && _icnt_cycle % _icnt_interval == 0) { + spdlog::info("[ICNT] Core->ICNT request {}GB/Sec", ((_memory_req_size*_nr_from_core*(1000/_icnt_period)/_icnt_interval))); + spdlog::info("[ICNT] Core<-ICNT request {}GB/Sec", ((_memory_req_size*_nr_to_core*(1000/_icnt_period)/_icnt_interval))); + spdlog::info("[ICNT] ICNT->MEM request {}GB/Sec", ((_memory_req_size*_nr_to_mem*(1000/_icnt_period)/_icnt_interval))); + spdlog::info("[ICNT] ICNT<-MEM request {}GB/Sec", ((_memory_req_size*_nr_from_mem*(1000/_icnt_period)/_icnt_interval))); + _nr_from_core=0; + _nr_to_core=0; + _nr_to_mem=0; + _nr_from_mem=0; + } + + _icnt->cycle(); } - } - if (_icnt_interval!=0 && _icnt_cycle % _icnt_interval == 0) { - spdlog::info("[ICNT] Core->ICNT request {}GB/Sec", ((_memory_req_size*_nr_from_core*(1000/_icnt_period)/_icnt_interval))); - spdlog::info("[ICNT] Core<-ICNT request {}GB/Sec", ((_memory_req_size*_nr_to_core*(1000/_icnt_period)/_icnt_interval))); - spdlog::info("[ICNT] ICNT->MEM request {}GB/Sec", ((_memory_req_size*_nr_to_mem*(1000/_icnt_period)/_icnt_interval))); - spdlog::info("[ICNT] ICNT<-MEM request {}GB/Sec", ((_memory_req_size*_nr_from_mem*(1000/_icnt_period)/_icnt_interval))); - _nr_from_core=0; - _nr_to_core=0; - _nr_to_mem=0; - _nr_from_mem=0; - } - _icnt->cycle(); } - } - spdlog::info("Simulation Finished at {} cycle {} us", _core_cycles, _core_cycles / (_config.core_freq) ); - /* Print simulation stats */ - for (int core_id = 0; core_id < _n_cores; core_id++) { - _cores[core_id]->print_stats(); - } - _icnt->print_stats(); - _dram->print_stat(); + + spdlog::info("Simulation Finished at {} cycle {} us", _core_cycles, _core_cycles / (_config.core_freq) ); + for (int core_id = 0; core_id < _n_cores; core_id++) { + _cores[core_id]->print_stats(); + } + _icnt->print_stats(); + _dram->print_stat(); + log_tensor_allocation_table(); } + void Simulator::register_model(std::unique_ptr model) { if(_weight_table.find(model->get_name()) == _weight_table.end()) { model->initialize_weight(_weight_table[model->get_name()]); @@ -275,4 +359,4 @@ const double Simulator::get_tile_ops() { return 0.0; else return _tile_timestamp.size() / duration.count(); -} \ No newline at end of file +} diff --git a/src/Simulator.h b/src/Simulator.h index d81be033..de2d428f 100644 --- a/src/Simulator.h +++ b/src/Simulator.h @@ -1,3 +1,4 @@ + #pragma once #include "Common.h" @@ -22,6 +23,9 @@ class Simulator { void run_simulator(); const double get_tile_ops(); const size_t get_number_tile() { return _tile_timestamp.size(); } + // Map memory requests/responses to tensor IDs +std::unordered_map _memaccess_to_tensor; + // void run_offline(std::string model_name, uint32_t sample_count); // void run_multistream(std::string model_name, uint32_t sample_count, // uint32_t ); void run_server(std::string trace_path); @@ -41,6 +45,8 @@ class Simulator { std::unique_ptr _icnt; std::unique_ptr _dram; std::unique_ptr _scheduler; + std::unique_ptr _active_model; // member variable + Model* _active_model_ptr = nullptr; // non-owning pointer for tracking // period information (ps) uint64_t _core_period; @@ -80,4 +86,5 @@ class Simulator { std::vector> _tile_timestamp; bool check_defined_model(std::string model_name); -}; \ No newline at end of file +}; + diff --git a/src/Tensor.cc b/src/Tensor.cc index 52e278b4..82f95633 100644 --- a/src/Tensor.cc +++ b/src/Tensor.cc @@ -3,6 +3,13 @@ #include "Model.h" #include "operations/Operation.h" +#include +#include + +// Define globals +std::unordered_map g_tensor_addr_map; +std::mutex g_tensor_map_mutex; + Tensor::Tensor(uint32_t src_node, onnx::TensorProto &tensor_proto, int precision, bool produced = false) { _id = generate_id(); @@ -102,15 +109,41 @@ void Tensor::add_child_node(Operation *op) { _child_nodes.push_back(op->get_id()); } -void Tensor::allocate_tensor(int precision) { - uint32_t size = 1; - for (auto dim : _dims) { - size *= dim; - } - _address = allocate_address(size * precision); - _size = size * precision; +void Tensor::allocate_tensor(int precision) +{ + uint32_t size = 1; + for (auto dim : _dims) + size *= dim; + + _address = allocate_address(size * precision); + _size = size * precision; + + // Register tensor info globally + std::lock_guard lock(g_tensor_map_mutex); + g_tensor_addr_map[_id] = { + _name, + static_cast(_address), + static_cast(_address + _size), + static_cast(_size) + }; + + spdlog::debug("Tensor registered: id={} name={} addr=0x{:x}-0x{:x} size={}", + _id, _name, _address, _address + _size, _size); } void Tensor::print_tensor() { spdlog::info("Tensor: {} {} {} {}", _name, _src_node, _dims, _size); +} + +void log_tensor_allocation_table() { + std::lock_guard lock(g_tensor_map_mutex); + + spdlog::info("{:<10} {:<20} {:<18} {:<18} {:<12}", + "TensorID", "Name", "StartAddr", "EndAddr", "Size"); + + for (auto &entry : g_tensor_addr_map) { + const auto &info = entry.second; + spdlog::info("{:<10} {:<20} 0x{:016x} - 0x{:016x} {:<12}", + entry.first, info.name, info.start_addr, info.end_addr, info.size); + } } \ No newline at end of file diff --git a/src/Tensor.h b/src/Tensor.h index 9d4f92a1..4cb3784a 100644 --- a/src/Tensor.h +++ b/src/Tensor.h @@ -3,6 +3,15 @@ class Model; class Operation; +struct TensorInfo { + std::string name; + uint64_t start_addr; + uint64_t end_addr; + uint64_t size; +}; + // Post-simulation logging +void log_tensor_allocation_table(); + class Tensor { public: diff --git a/src/operations/AdaptiveAvgPool.cc b/src/operations/AdaptiveAvgPool.cc index 7b13fe9d..e667d80f 100644 --- a/src/operations/AdaptiveAvgPool.cc +++ b/src/operations/AdaptiveAvgPool.cc @@ -72,5 +72,28 @@ void AdaptiveAvgPool::initialize_tiles(MappingTable& mapping_table) { } void AdaptiveAvgPool::initialize_instructions(Tile* tile, Mapping mapping) { - return; -} \ No newline at end of file + if (_outputs.empty()) return; // no tensor to track + + Tensor* output_tensor = _model->get_tensor(_outputs[0]); // get tensor pointer + if (!output_tensor) return; + + addr_type sram_base = SPAD_BASE; // example SRAM location + uint32_t tensor_size = 1; + for (auto dim : output_tensor->get_dims()) tensor_size *= dim; + tensor_size *= _config.precision; + + // MOVOUT instruction: write back result to DRAM +tile->instructions.push_back(std::make_unique(Instruction{ + .opcode = Opcode::MOVOUT, + .id = "", // or some string if needed + .dependent_ids = {}, // empty vector since not used here + .dest_id = std::to_string(output_tensor->get_id()), // <-- link tensor ID + .dest_addr = sram_base, + .size = tensor_size, + .src_addrs = {sram_base}, + .operand_id = _OUTPUT_OPERAND +})); + + spdlog::info("[AdaptiveAvgPool] Instruction created for tensor ID {}", + output_tensor->get_id()); +} diff --git a/src/operations/Attention.cc b/src/operations/Attention.cc index 3688a44a..6067267f 100644 --- a/src/operations/Attention.cc +++ b/src/operations/Attention.cc @@ -59,6 +59,11 @@ Attention::Attention(SimulationConfig config, Model* model, } else { pre_defind_tensor->redefine_tensor(_id, _output_shape); } + uint32_t tensor_id = (pre_defind_tensor != nullptr) + ? pre_defind_tensor->get_id() + : _outputs.back(); // last pushed when we created new tensor + +uint32_t tensor_id_str = tensor_id; } Attention::Attention(SimulationConfig config, Model* model, @@ -71,7 +76,7 @@ Attention::Attention(SimulationConfig config, Model* model, _dmodel = std::stoi(get_attribute("hidden_size")); _dk = _dmodel / _nh; } - + //here we need to pass the id void Attention::initialize_tiles(MappingTable& mapping_table) { if(_outputs.empty()) { _output_shape = {_q_len, _dmodel}; @@ -126,6 +131,8 @@ void Attention::initialize_tiles(MappingTable& mapping_table) { }); /* dummy mapping */ _tiles.push_back(std::move(tile)); + //added this line here + _tiles.back()->tensor_id = _outputs.back(); // assign the output tensor ID initialize_instructions(_tiles.back().get(), mapping, head_off, heads_per_kv); } } @@ -151,7 +158,12 @@ void Attention::initialize_tiles(MappingTable& mapping_table) { kv_flops / _config.max_systolic_flops(target_core) * 1e3); } +//dummy void Attention::initialize_onnx_tiles(MappingTable& mapping_table) { + initialize_onnx_tiles(mapping_table, 0); +} + +void Attention::initialize_onnx_tiles(MappingTable& mapping_table, uint32_t tensor_id_str) { calculate_loops(); /* Check using fusion */ if (!use_fused) { @@ -210,6 +222,9 @@ void Attention::initialize_onnx_tiles(MappingTable& mapping_table) { }); /* dummy mapping */ _tiles.push_back(std::move(tile)); + + tile->tensor_id = tensor_id_str; // ✅ assign the correct field here + initialize_instructions(_tiles.back().get(), head_off, heads_per_tile); } } @@ -329,6 +344,8 @@ void Attention::initialize_instructions(Tile* tile, int head_idx, int num_heads) // MOVOUT tile->instructions.push_back(std::make_unique(Instruction{ .opcode = Opcode::MOVOUT, + .tensor_id = tile->tensor_id, + .dest_addr = sram_l_ofs, .size = (uint32_t)dram_output_addrs.size(), .src_addrs = std::vector(dram_output_addrs.begin(), dram_output_addrs.end()), @@ -569,6 +586,9 @@ void Attention::initialize_instructions(Tile* tile, Mapping mapping, int head_id // MOVOUT tile->instructions.push_back(std::make_unique(Instruction{ .opcode = Opcode::MOVOUT, + .tensor_id = tile->tensor_id, + + .dest_addr = sram_l_ofs, .size = (uint32_t)dram_output_addrs.size(), .src_addrs = std::vector(dram_output_addrs.begin(), dram_output_addrs.end()), @@ -723,4 +743,5 @@ void Attention::calculate_loops(Mapping& mapping) { } } -uint32_t Attention::sram_size_needed() { return 0; } \ No newline at end of file +uint32_t Attention::sram_size_needed() { return 0; } + diff --git a/src/operations/Attention.h b/src/operations/Attention.h index 08b2629b..7598c7ae 100644 --- a/src/operations/Attention.h +++ b/src/operations/Attention.h @@ -52,6 +52,7 @@ class Attention : public Operation { //void initialize_instructions(Tile &tile, int req_idx, int head_idx, int num_heads); void initialize_tiles(MappingTable& mapping_table) override; void initialize_onnx_tiles(MappingTable& mapping_table); + void initialize_onnx_tiles(MappingTable& mapping_table,uint32_t tensor_id_str ); void initialize_non_fused_tiles(MappingTable& mapping_table); void initialize_instructions(Tile* tile, Mapping mapping, int head_idx, int num_heads); void initialize_instructions(Tile* tile, int head_idx, int num_heads); diff --git a/src/operations/GlobalAvgPool.cc b/src/operations/GlobalAvgPool.cc index 0af06f7b..1eb024fc 100644 --- a/src/operations/GlobalAvgPool.cc +++ b/src/operations/GlobalAvgPool.cc @@ -3,6 +3,7 @@ #include "../Model.h" + GlobalAvgPool::GlobalAvgPool(SimulationConfig config, Model* model, onnx::NodeProto& node_proto, uint32_t target_core) : Operation(config, model, node_proto, target_core) { @@ -56,6 +57,7 @@ void GlobalAvgPool::initialize_tiles(MappingTable& mapping_table) { } void GlobalAvgPool::initialize_instructions(Tile* tile, Mapping mapping) { + //uncommented these // std::vector output_shape = get_output(0)->get_dims(); // std::vector input_shape = get_input(0)->get_dims(); diff --git a/src/operations/Operation.cc b/src/operations/Operation.cc index 79da1017..0d6825b3 100644 --- a/src/operations/Operation.cc +++ b/src/operations/Operation.cc @@ -117,7 +117,7 @@ void Operation::set_finish() { for (auto id : _outputs) { Tensor* output = _model->get_tensor(id); output->set_produced(); - } + } _finish = true; spdlog::trace("layer {} finish", _name.c_str()); } @@ -154,6 +154,7 @@ bool Operation::check_executable() { for (auto id : _inputs) { Tensor* input = _model->get_tensor(id); result = result && input->get_produced(); + spdlog::trace("Layer {}: Input {} Produced {}", _name.c_str(), input->get_name().c_str(), input->get_produced()); } diff --git a/tmp.onnx b/tmp.onnx new file mode 100644 index 00000000..9dfa99d8 Binary files /dev/null and b/tmp.onnx differ diff --git a/traces/resnet18.csv b/traces/resnet18.csv new file mode 100644 index 00000000..1ae008e2 --- /dev/null +++ b/traces/resnet18.csv @@ -0,0 +1,21 @@ +time,prompt_length,target_length,cached_length +0,1204224,1000,0 +117,150528,1000,0 +225,1204224,1000,0 +352,150528,1000,0 +461,150528,1000,0 +562,150528,1000,0 +636,1204224,1000,0 +754,1204224,1000,0 +943,1204224,1000,0 +995,301056,1000,0 +1193,1204224,1000,0 +1275,1204224,1000,0 +1375,301056,1000,0 +1461,150528,1000,0 +1555,602112,1000,0 +1616,150528,1000,0 +1726,602112,1000,0 +1797,150528,1000,0 +1871,1204224,1000,0 +2046,1204224,1000,0