| // Copyright 2025 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "hw_sim/hw_primitives.h" |
| |
| Clock::Observer::Observer(Clock* clock) |
| : clock_(clock) { |
| clock_->AddObserver(this); |
| } |
| |
| Clock::Observer::~Observer() { |
| clock_->RemoveObserver(this); |
| } |
| |
| void Clock::Step() { |
| context_->timeInc(1); |
| (*clock_) = 1; |
| Eval(); |
| for (auto& observer : observers_) { |
| observer->OnRisingEdge(); |
| Eval(); |
| } |
| |
| context_->timeInc(1); |
| (*clock_) = 0; |
| Eval(); |
| for (auto& observer : observers_) { |
| observer->OnFallingEdge(); |
| Eval(); |
| } |
| } |
| |
| void Clock::Eval() { |
| eval_function_(); |
| } |
| |
| void Clock::AddObserver(Observer* observer) { |
| observers_.push_back(observer); |
| } |
| |
| void Clock::RemoveObserver(Observer* observer) { |
| auto it = std::find(observers_.begin(), observers_.end(), observer); |
| if (it != observers_.end()) { |
| observers_.erase(it); |
| } |
| } |
| |
| // static |
| AxiAddr AxiAddr::FromIdAddrSize(int id, uint32_t addr, uint32_t byte_length) { |
| uint32_t start_addr = addr; |
| uint32_t end_addr = addr + byte_length - 1; |
| uint32_t start_line = start_addr / 16; |
| uint32_t end_line = end_addr / 16; |
| uint32_t beats = (end_line - start_line) + 1; |
| uint32_t size = std::ceil(std::log2(byte_length)); |
| size = std::min(size, 4u); |
| AxiAddr axi_addr; |
| axi_addr.addr_bits_addr = addr; |
| axi_addr.addr_bits_prot = 0; |
| axi_addr.addr_bits_id = id; |
| axi_addr.addr_bits_len = beats - 1; |
| axi_addr.addr_bits_size = size; |
| axi_addr.addr_bits_burst = 1; // INCR |
| axi_addr.addr_bits_lock = 0; |
| axi_addr.addr_bits_cache = 0; |
| axi_addr.addr_bits_qos = 0; |
| axi_addr.addr_bits_region = 0; |
| return axi_addr; |
| } |
| |