/* * Copyright (c) 2008-2022 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU * General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ # include "vvp_island.h" # include "compile.h" # include "symbols.h" # include "schedule.h" # include "config.h" #ifdef CHECK_WITH_VALGRIND # include "vvp_cleanup.h" #endif # include # include # include # include # include # include "ivl_alloc.h" using namespace std; #ifdef CHECK_WITH_VALGRIND static bool at_EOS = false; #endif void island_send_value(vvp_net_t*net, const vvp_vector8_t&val) { vvp_island_port*fun = dynamic_cast(net->fun); if (fun->outvalue .eeq(val)) return; fun->outvalue = val; net->send_vec8(fun->outvalue); } /* * Implementations... */ vvp_island::vvp_island() { flagged_ = false; branches_ = 0; ports_ = 0; anodes_ = 0; bnodes_ = 0; } vvp_island::~vvp_island() { // We can only delete islands at the end of simulation. #ifdef CHECK_WITH_VALGRIND if (!at_EOS) assert(0); #endif while (branches_) { vvp_island_branch *next_br = branches_->next_branch; delete branches_; branches_ = next_br; } } void vvp_island::flag_island() { if (flagged_ == true) return; schedule_generic(this, 0, false, false); flagged_ = true; } /* * This method handles the callback from the scheduler. It does basic * housecleaning and calls the run_island() method implemented by the * derived class. */ void vvp_island::run_run() { flagged_ = false; run_island(); } void vvp_island::add_port(const char*key, vvp_net_t*net) { if (ports_ == 0) ports_ = new symbol_map_s; // each port should have a unique label assert(ports_->sym_get_value(key) == 0); ports_->sym_set_value(key, net); } void vvp_island::add_branch(vvp_island_branch*branch, const char*pa, const char*pb) { vvp_island_branch*cur; assert(ports_); branch->a = ports_->sym_get_value(pa); branch->b = ports_->sym_get_value(pb); assert(branch->a && branch->b); vvp_branch_ptr_t ptra (branch, 0); vvp_branch_ptr_t ptrb (branch, 1); if (anodes_ == 0) anodes_ = new symbol_map_s; if (bnodes_ == 0) bnodes_ = new symbol_map_s; if ((cur = anodes_->sym_get_value(pa))) { branch->link[0] = cur->link[0]; cur->link[0] = ptra; } else if ((cur = bnodes_->sym_get_value(pa))) { branch->link[0] = cur->link[1]; cur->link[1] = ptra; } else { branch->link[0] = ptra; anodes_->sym_set_value(pa, branch); } if ((cur = anodes_->sym_get_value(pb))) { branch->link[1] = cur->link[0]; cur->link[0] = ptrb; } else if ((cur = bnodes_->sym_get_value(pb))) { branch->link[1] = cur->link[1]; cur->link[1] = ptrb; } else { branch->link[1] = ptrb; bnodes_->sym_set_value(pb, branch); } branch->next_branch = branches_; branches_ = branch; } vvp_net_t* vvp_island::find_port(const char*key) { if (ports_ == 0) return 0; else return ports_->sym_get_value(key); } void vvp_island::compile_cleanup() { delete ports_; ports_ = 0; delete anodes_; anodes_ = 0; delete bnodes_; bnodes_ = 0; } vvp_island_port::vvp_island_port(vvp_island*ip) : island_(ip) { } vvp_island_port::~vvp_island_port() { } void vvp_island_port::recv_vec4(vvp_net_ptr_t, const vvp_vector4_t&bit, vvp_context_t) { vvp_vector8_t tmp (bit, 6, 6); if (invalue .eeq(tmp)) return; invalue = tmp; island_->flag_island(); } void vvp_island_port::recv_vec4_pv(vvp_net_ptr_t port, const vvp_vector4_t&bit, unsigned base, unsigned vwid, vvp_context_t) { vvp_vector8_t tmp(bit, 6, 6); recv_vec8_pv(port, tmp, base, vwid); } void vvp_island_port::recv_vec8(vvp_net_ptr_t, const vvp_vector8_t&bit) { if (invalue .eeq(bit)) return; invalue = bit; island_->flag_island(); } void vvp_island_port::recv_vec8_pv(vvp_net_ptr_t, const vvp_vector8_t&bit, unsigned base, unsigned vwid) { if (invalue.size() == 0) { invalue = part_expand(bit, vwid, base); } else { unsigned wid = bit.size(); assert(invalue.size() == vwid); for (unsigned idx = 0; idx < wid ; idx += 1) { if ((base+idx) >= vwid) break; invalue.set_bit(base+idx, bit.value(idx)); } } island_->flag_island(); } void vvp_island_port::force_flag(bool run_now) { if (run_now) island_->run_island(); else island_->flag_island(); } vvp_island_branch::~vvp_island_branch() { } void island_collect_node(list&conn, vvp_branch_ptr_t cur) { conn .push_back(cur); for (vvp_branch_ptr_t idx = next(cur) ; idx != cur ; idx = next(idx)) conn.push_back(idx); } /* **** COMPILE/LINK SUPPORT **** */ /* * We need to keep an island symbol table to make island labels to * islands, and we need a list of the islands that we can run through * during cleanup. After linking is done, the compile_island_cleanup() is * called to erase the symbol table, we still need the list to cleanup the * island memory at EOS. */ static symbol_map_s* island_table = 0; static vvp_island** island_list = 0; static unsigned island_count = 0; #ifdef CHECK_WITH_VALGRIND void island_delete() { at_EOS = true; for (unsigned idx = 0; idx < island_count; idx += 1) { delete island_list[idx]; } free(island_list); island_list = 0; island_count = 0; } #endif void compile_island_base(char*label, vvp_island*use_island) { if (island_table == 0) island_table = new symbol_map_s; island_table->sym_set_value(label, use_island); island_count += 1; island_list = (vvp_island **)realloc(island_list, island_count*sizeof(vvp_island **)); island_list[island_count-1] = use_island; free(label); } vvp_island* compile_find_island(const char*island) { assert(island_table); vvp_island*use_island = island_table->sym_get_value(island); assert(use_island); return use_island; } /* * This handles the compile of a .port record. A .port is a 2-way port * between the island and the outside. For example, * *