Merge branch 'develop'
# Conflicts: # .cproject # .gitmodules # .settings/language.settings.xml # conanfile.txt # examples/simple_system/CMakeLists.txt # examples/simple_system/gen/e300_plat_t.h # examples/simple_system/gpio.cpp # examples/simple_system/plic.cpp # examples/simple_system/sc_main.cpp # examples/simple_system/simple_system.cpp # examples/transaction_recording/CMakeLists.txt # examples/transaction_recording/scv_tr_recording_example.cpp
This commit is contained in:
		| @@ -1,6 +1,4 @@ | ||||
| cmake_minimum_required(VERSION 3.3) | ||||
| # Add executable called "simple_system" that is built from the source files | ||||
| # "scv_tr_recording_example.cpp". The extensions are automatically found. | ||||
| cmake_minimum_required(VERSION 3.12) | ||||
| add_executable (simple_system  | ||||
|     plic.cpp | ||||
|     uart.cpp | ||||
| @@ -10,9 +8,5 @@ add_executable (simple_system | ||||
|     simple_system.cpp | ||||
|     sc_main.cpp | ||||
| ) | ||||
| # Link the executable to the sc_components library. Since the sc_components library has | ||||
| # public include directories we will use those link directories when building | ||||
| # simple_system | ||||
| target_link_libraries (simple_system LINK_PUBLIC scc) | ||||
| target_link_libraries (simple_system LINK_PUBLIC ${Boost_LIBRARIES} ) | ||||
| target_link_libraries (simple_system LINK_PUBLIC ${ZLIB_LIBRARY}) | ||||
|   | ||||
| @@ -17,11 +17,11 @@ | ||||
| #define _E300_PLAT_MAP_H_ | ||||
| // need double braces, see | ||||
| // https://stackoverflow.com/questions/6893700/how-to-construct-stdarray-object-with-initializer-list#6894191 | ||||
| const std::array<scc::target_memory_map_entry<32>, 4> e300_plat_map = {{ | ||||
|     {i_plic.socket, 0x0c000000, 0x200008}, | ||||
|     {i_gpio.socket, 0x10012000, 0x1000}, | ||||
|     {i_uart.socket, 0x10013000, 0x1000}, | ||||
|     {i_spi.socket, 0x10014000, 0x1000}, | ||||
| const std::array<scc::target_name_map_entry<32>, 4> e300_plat_map = {{ | ||||
|     {"plic", 0x0c000000, 0x200008}, | ||||
|     {"gpio", 0x10012000, 0x1000}, | ||||
|     {"uart", 0x10013000, 0x1000}, | ||||
|     {"spi",  0x10014000, 0x1000}, | ||||
| }}; | ||||
|  | ||||
| #endif /* _E300_PLAT_MAP_H_ */ | ||||
|   | ||||
| @@ -44,7 +44,7 @@ | ||||
| namespace sysc { | ||||
|  | ||||
| class gpio_regs : public sc_core::sc_module, public scc::resetable { | ||||
| protected: | ||||
| public: | ||||
|     // storage declarations | ||||
|     uint32_t r_value; | ||||
|  | ||||
|   | ||||
| @@ -1,47 +1,224 @@ | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| // Copyright 2017 eyck@minres.com | ||||
| // Copyright (C) 2017, MINRES Technologies GmbH | ||||
| // All rights reserved. | ||||
| // | ||||
| // 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 | ||||
| // Redistribution and use in source and binary forms, with or without | ||||
| // modification, are permitted provided that the following conditions are met: | ||||
| // | ||||
| // 1. Redistributions of source code must retain the above copyright notice, | ||||
| //    this list of conditions and the following disclaimer. | ||||
| // | ||||
| // 2. Redistributions in binary form must reproduce the above copyright notice, | ||||
| //    this list of conditions and the following disclaimer in the documentation | ||||
| //    and/or other materials provided with the distribution. | ||||
| // | ||||
| // 3. Neither the name of the copyright holder nor the names of its contributors | ||||
| //    may be used to endorse or promote products derived from this software | ||||
| //    without specific prior written permission. | ||||
| // | ||||
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||
| // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||
| // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||
| // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||||
| // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||
| // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||
| // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||
| // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||
| // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||
| // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||||
| // POSSIBILITY OF SUCH DAMAGE. | ||||
| // | ||||
| // Contributors: | ||||
| //       eyck@minres.com - initial implementation | ||||
| // | ||||
| //   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 "gpio.h" | ||||
| #include "gen/gpio_regs.h" | ||||
| #include "scc/report.h" | ||||
| #include "scc/utilities.h" | ||||
| #include "gen/gpio_regs.h" | ||||
| #include <limits> | ||||
|  | ||||
| namespace sysc { | ||||
|  | ||||
| gpio::gpio(sc_core::sc_module_name nm) | ||||
| : sc_core::sc_module(nm) | ||||
| using namespace sc_core; | ||||
|  | ||||
| gpio::gpio(sc_module_name nm) | ||||
| : sc_module(nm) | ||||
| , tlm_target<>(clk) | ||||
| , NAMED(clk_i) | ||||
| , NAMED(rst_i) | ||||
| , NAMEDD(regs, gpio_regs) { | ||||
| , NAMED(pins_o, 32) | ||||
| , NAMED(pins_i, 32) | ||||
| , NAMED(iof0_o, 32) | ||||
| , NAMED(iof1_o, 32) | ||||
| , NAMED(iof0_i, 32) | ||||
| , NAMED(iof1_i, 32) | ||||
| , NAMEDD(regs, gpio_regs) | ||||
| { | ||||
|     regs->registerResources(*this); | ||||
|     SC_METHOD(clock_cb); | ||||
|     sensitive << clk_i; | ||||
|     SC_METHOD(reset_cb); | ||||
|     sensitive << rst_i; | ||||
|     dont_initialize(); | ||||
|     auto pins_i_cb =[this](unsigned int tag, tlm::tlm_signal_gp<>& gp, | ||||
|             tlm::tlm_phase& phase, sc_time& delay)->tlm::tlm_sync_enum{ | ||||
|         this->pin_input(tag, gp, delay); | ||||
|         return tlm::TLM_COMPLETED; | ||||
|     }; | ||||
|     auto i=0U; | ||||
|     for(auto& s:pins_i){ | ||||
|         s.register_nb_transport(pins_i_cb, i); | ||||
|         ++i; | ||||
|     } | ||||
|     auto iof0_i_cb =[this](unsigned int tag, tlm::tlm_signal_gp<>& gp, | ||||
|             tlm::tlm_phase& phase, sc_time& delay)->tlm::tlm_sync_enum{ | ||||
|         last_iof0[tag]=gp.get_value(); | ||||
|         this->iof_input(tag, 0, gp, delay); | ||||
|         return tlm::TLM_COMPLETED; | ||||
|     }; | ||||
|     i=0; | ||||
|     for(auto& s:iof0_i){ | ||||
|         s.register_nb_transport(iof0_i_cb, i); | ||||
|         ++i; | ||||
|     } | ||||
|     auto iof1_i_cb =[this](unsigned int tag, tlm::tlm_signal_gp<>& gp, | ||||
|             tlm::tlm_phase& phase, sc_time& delay)->tlm::tlm_sync_enum{ | ||||
|         last_iof1[tag]=gp.get_value(); | ||||
|         this->iof_input(tag, 1, gp, delay); | ||||
|         return tlm::TLM_COMPLETED; | ||||
|     }; | ||||
|     i=0; | ||||
|     for(auto& s:iof1_i){ | ||||
|         s.register_nb_transport(iof1_i_cb, i); | ||||
|         ++i; | ||||
|     } | ||||
|     auto update_pins_cb = [this](scc::sc_register<uint32_t> ®, uint32_t data, sc_time d) -> bool { | ||||
|         if (!this->regs->in_reset()) { | ||||
|             auto changed_bits = (reg.get()^data); | ||||
|             reg.put(data); | ||||
|             update_pins(changed_bits); | ||||
|         } | ||||
|         return true; | ||||
|     }; | ||||
|     regs->port.set_write_cb(update_pins_cb); | ||||
|     regs->output_en.set_write_cb(update_pins_cb); | ||||
|     regs->out_xor.set_write_cb(update_pins_cb); | ||||
|     regs->iof_en.set_write_cb(update_pins_cb); | ||||
|     regs->iof_sel.set_write_cb(update_pins_cb); | ||||
| } | ||||
|  | ||||
| gpio::~gpio() {} | ||||
|  | ||||
| void gpio::clock_cb() {} | ||||
|  | ||||
| void gpio::reset_cb() { | ||||
|     if (rst_i.read()) | ||||
|     if (rst_i.read()){ | ||||
|         regs->reset_start(); | ||||
|     else | ||||
|     } else { | ||||
|         regs->reset_stop(); | ||||
|     } | ||||
|     update_pins(std::numeric_limits<uint32_t>::max()); | ||||
| } | ||||
|  | ||||
| void gpio::clock_cb() { | ||||
| 	this->clk = clk_i.read(); | ||||
| } | ||||
|  | ||||
| tlm::tlm_phase gpio::write_output(tlm::tlm_signal_gp<bool>& gp, size_t i, bool val) { | ||||
|     sc_time delay{SC_ZERO_TIME}; | ||||
|     tlm::tlm_phase phase{ tlm::BEGIN_REQ }; | ||||
|     gp.set_command(tlm::TLM_WRITE_COMMAND); | ||||
|     gp.set_response_status(tlm::TLM_OK_RESPONSE); | ||||
|     gp.set_value(val); | ||||
|     pins_o.at(i)->nb_transport_fw(gp, phase, delay); | ||||
|     return phase; | ||||
| } | ||||
|  | ||||
| void gpio::update_pins(uint32_t changed_bits) { | ||||
|     sc_inout_rv<32>::data_type out_val; | ||||
|     tlm::tlm_signal_gp<bool> gp; | ||||
|     bool val; | ||||
|     for(size_t i=0, mask = 1; i<32; ++i, mask<<=1){ | ||||
|         if(changed_bits&mask){ | ||||
|             if((regs->r_iof_en&mask!=0) && (iof0_i[i].size()==0 || iof1_i[i].size()==0)){ | ||||
|                 if((regs->r_iof_sel&mask)==0 && iof0_i[i].size()>0){ | ||||
|                     val=last_iof0[i]?sc_dt::Log_1:sc_dt::Log_0; | ||||
|                 } else if((regs->r_iof_sel&mask)==1 && iof1_i[i].size()>0) | ||||
|                     val=last_iof1[i]?sc_dt::Log_1:sc_dt::Log_0; | ||||
|             } else { | ||||
|                 if((regs->r_output_en&mask) && (regs->r_port&mask)) | ||||
|                     val=true; | ||||
|                 else | ||||
|                     val=false; | ||||
|                 if(regs->r_out_xor&mask) | ||||
|                     val=~val; | ||||
|             } | ||||
|             tlm::tlm_phase phase = write_output(gp, i, val); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| void gpio::pin_input(unsigned int tag, tlm::tlm_signal_gp<bool>& gp, sc_time& delay) { | ||||
|     if(delay>SC_ZERO_TIME){ | ||||
|         wait(delay); | ||||
|         delay=SC_ZERO_TIME; | ||||
|     } | ||||
|     auto mask = 1u<<tag; | ||||
|     switch(gp.get_value()){ | ||||
|     case true: | ||||
|         if(regs->r_output_en&mask==0) | ||||
|             regs->r_value|=mask; | ||||
|         forward_pin_input(tag, gp); | ||||
|         break; | ||||
|     case false: | ||||
|         if(regs->r_output_en&mask==0) regs->r_value&=~mask; | ||||
|         forward_pin_input(tag, gp); | ||||
|         break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| void gpio::forward_pin_input(unsigned int tag, tlm::tlm_signal_gp<bool>& gp) { | ||||
|     const auto mask = 1U<<tag; | ||||
|     if(regs->iof_en&mask){ | ||||
|         auto& socket = regs->iof_sel&mask?iof1_o[tag]:iof0_o[tag]; | ||||
|         tlm::tlm_signal_gp<> new_gp; | ||||
|         for(size_t i=0; i<socket.size(); ++i){ | ||||
|             sc_time delay{SC_ZERO_TIME}; | ||||
|             tlm::tlm_phase phase{tlm::BEGIN_REQ}; | ||||
|             new_gp.set_command(tlm::TLM_WRITE_COMMAND); | ||||
|             new_gp.set_response_status(tlm::TLM_OK_RESPONSE); | ||||
|             new_gp.set_value(gp.get_value()); | ||||
|             new_gp.update_extensions_from(gp); | ||||
|             socket->nb_transport_fw(new_gp, phase, delay); // we don't care about phase and sync enum | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| void gpio::iof_input(unsigned int tag, unsigned iof_idx, tlm::tlm_signal_gp<>& gp, sc_time& delay) { | ||||
|     if(delay>SC_ZERO_TIME){ | ||||
|          wait(delay); | ||||
|          delay=SC_ZERO_TIME; | ||||
|     } | ||||
|     const auto mask = 1U<<tag; | ||||
|     if(regs->r_iof_en&mask){ | ||||
|         const auto idx = regs->r_iof_sel&mask?1:0; | ||||
|         if(iof_idx == idx){ | ||||
|             auto& socket = pins_o[tag]; | ||||
|             for(size_t i=0; i<socket.size(); ++i){ | ||||
|                 sc_time delay{SC_ZERO_TIME}; | ||||
|                 tlm::tlm_phase phase{tlm::BEGIN_REQ}; | ||||
|                 tlm::tlm_signal_gp<> new_gp; | ||||
|                 new_gp.set_command(tlm::TLM_WRITE_COMMAND); | ||||
|                 auto val = gp.get_value(); | ||||
|                 new_gp.set_value(val); | ||||
|                 new_gp.copy_extensions_from(gp); | ||||
|                 socket->nb_transport_fw(new_gp, phase, delay); // we don't care about phase and sync enum | ||||
|                 gp.update_extensions_from(new_gp); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| } /* namespace sysc */ | ||||
|  | ||||
|   | ||||
| @@ -1,41 +1,84 @@ | ||||
| /******************************************************************************* | ||||
|  * Copyright 2017 eyck@minres.com | ||||
|  * | ||||
|  * 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. | ||||
|  ******************************************************************************/ | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| // Copyright (C) 2017, MINRES Technologies GmbH | ||||
| // All rights reserved. | ||||
| // | ||||
| // Redistribution and use in source and binary forms, with or without | ||||
| // modification, are permitted provided that the following conditions are met: | ||||
| // | ||||
| // 1. Redistributions of source code must retain the above copyright notice, | ||||
| //    this list of conditions and the following disclaimer. | ||||
| // | ||||
| // 2. Redistributions in binary form must reproduce the above copyright notice, | ||||
| //    this list of conditions and the following disclaimer in the documentation | ||||
| //    and/or other materials provided with the distribution. | ||||
| // | ||||
| // 3. Neither the name of the copyright holder nor the names of its contributors | ||||
| //    may be used to endorse or promote products derived from this software | ||||
| //    without specific prior written permission. | ||||
| // | ||||
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||
| // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||
| // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||
| // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | ||||
| // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||||
| // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||||
| // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||||
| // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||||
| // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||||
| // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||||
| // POSSIBILITY OF SUCH DAMAGE. | ||||
| // | ||||
| // Contributors: | ||||
| //       eyck@minres.com - initial implementation | ||||
| // | ||||
| // | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| #ifndef _GPIO_H_ | ||||
| #define _GPIO_H_ | ||||
|  | ||||
| #include <scc/tlm_target.h> | ||||
| #include "scc/tlm_target.h" | ||||
| #include "scc/signal_target_mixin.h" | ||||
| #include "scc/signal_initiator_mixin.h" | ||||
| #include <tlm/tlm_signal.h> | ||||
|  | ||||
| namespace sysc { | ||||
|  | ||||
| class gpio_regs; | ||||
| class WsHandler; | ||||
|  | ||||
| class gpio : public sc_core::sc_module, public scc::tlm_target<> { | ||||
| public: | ||||
|     SC_HAS_PROCESS(gpio); | ||||
|     sc_core::sc_in<sc_core::sc_time> clk_i; | ||||
|     sc_core::sc_in<bool> rst_i; | ||||
|     // sc_core::sc_inout_rv<32> pins_io; | ||||
|  | ||||
|     sc_core::sc_vector<scc::tlm_signal_bool_out> pins_o; | ||||
|     sc_core::sc_vector<scc::tlm_signal_bool_in>  pins_i; | ||||
|  | ||||
|     sc_core::sc_vector<scc::tlm_signal_bool_opt_out> iof0_o; | ||||
|     sc_core::sc_vector<scc::tlm_signal_bool_opt_out> iof1_o; | ||||
|     sc_core::sc_vector<scc::tlm_signal_bool_opt_in>  iof0_i; | ||||
|     sc_core::sc_vector<scc::tlm_signal_bool_opt_in>  iof1_i; | ||||
|  | ||||
|     gpio(sc_core::sc_module_name nm); | ||||
|     virtual ~gpio(); | ||||
|     virtual ~gpio() override; // need to keep it in source file because of fwd declaration of gpio_regs | ||||
|  | ||||
| protected: | ||||
|     void clock_cb(); | ||||
|     void reset_cb(); | ||||
|     void update_pins(uint32_t changed_bits); | ||||
|     void pin_input(unsigned int tag, tlm::tlm_signal_gp<>& gp, sc_core::sc_time& delay); | ||||
|     void forward_pin_input(unsigned int tag, tlm::tlm_signal_gp<>& gp); | ||||
|     void iof_input(unsigned int tag, unsigned iof_idx, tlm::tlm_signal_gp<>& gp, sc_core::sc_time& delay); | ||||
|     sc_core::sc_time clk; | ||||
|     std::array<bool, 32> last_iof0, last_iof1; | ||||
|     std::unique_ptr<gpio_regs> regs; | ||||
|     std::shared_ptr<sysc::WsHandler> handler; | ||||
|  | ||||
| private: | ||||
|     tlm::tlm_phase write_output(tlm::tlm_signal_gp<>& gp, size_t i, bool val); | ||||
| }; | ||||
|  | ||||
| } /* namespace sysc */ | ||||
|   | ||||
| @@ -119,7 +119,7 @@ void plic::global_int_port_cb() { | ||||
|  | ||||
|         if (enable && global_interrupts_i[i].read() == 1) { | ||||
|             regs->r_pending = regs->r_pending | (0x1 << i); | ||||
|             LOG(INFO) << "pending interrupt identified: " << i; | ||||
|             SCDEBUG("plic") << "pending interrupt identified: " << i; | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -147,7 +147,7 @@ void plic::handle_pending_int() { | ||||
|                 claim_prio = prio; | ||||
|                 claim_int = i; | ||||
|                 raise_int = 1; | ||||
|                 LOG(INFO) << "pending interrupt activated: " << i; | ||||
|                 SCDEBUG("plic") << "pending interrupt activated: " << i; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| @@ -158,14 +158,14 @@ void plic::handle_pending_int() { | ||||
|         // todo: evluate clock period | ||||
|     } else { | ||||
|         regs->r_claim_complete = 0; | ||||
|         LOG(INFO) << "no further pending interrupt."; | ||||
|         SCDEBUG("plic") << "no further pending interrupt."; | ||||
|     } | ||||
| } | ||||
|  | ||||
| void plic::reset_pending_int(uint32_t irq) { | ||||
|     // todo: evaluate enable register (see spec) | ||||
|     // todo: make sure that pending is set, otherwise don't reset irq ... read spec. | ||||
|     LOG(INFO) << "reset pending interrupt: " << irq; | ||||
|     SCDEBUG("plic") << "reset pending interrupt: " << irq; | ||||
|     // reset related pending bit | ||||
|     regs->r_pending &= ~(0x1 << irq); | ||||
|     core_interrupt_o.write(0); | ||||
|   | ||||
| @@ -24,9 +24,7 @@ | ||||
| #include <scc/report.h> | ||||
| #include <scc/scv_tr_db.h> | ||||
| #include <scc/tracer.h> | ||||
| #include <cci_utils/broker.h> | ||||
| #include <boost/program_options.hpp> | ||||
| #include <sstream> | ||||
|  | ||||
| using namespace sysc; | ||||
| using namespace scc; | ||||
| @@ -42,10 +40,6 @@ int sc_main(int argc, char *argv[]) { | ||||
|     sc_core::sc_report_handler::set_actions( "/IEEE_Std_1666/deprecated", sc_core::SC_DO_NOTHING ); | ||||
|     sc_core::sc_report_handler::set_actions(sc_core::SC_ID_MORE_THAN_ONE_SIGNAL_DRIVER_, sc_core::SC_DO_NOTHING); | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     // create global CCI broker | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     cci::cci_register_broker(new cci_utils::broker("Global Broker")); | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     // CLI argument parsing | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     po::options_description desc("Options"); | ||||
| @@ -77,14 +71,13 @@ int sc_main(int argc, char *argv[]) { | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     // set up tracing & transaction recording | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     tracer trace("simple_system", tracer::TEXT, vm.count("trace")); | ||||
|     tracer trace("simple_system", tracer::COMPRESSED, vm.count("trace")); | ||||
|     // todo: fix displayed clock period in VCD | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     // instantiate top level | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     simple_system i_simple_system("i_simple_system"); | ||||
|     // sr_report_handler::add_sc_object_to_filter(&i_simple_system.i_master, sc_core::SC_WARNING, sc_core::SC_MEDIUM); | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     // run simulation | ||||
| @@ -93,7 +86,7 @@ int sc_main(int argc, char *argv[]) { | ||||
|     // todo: provide end-of-simulation macros | ||||
|  | ||||
|     if (!sc_core::sc_end_of_simulation_invoked()) { | ||||
|         LOG(ERROR) << "simulation timed out"; | ||||
|         SCERR() << "simulation timed out"; | ||||
|         sc_core::sc_stop(); | ||||
|     } | ||||
|     return SUCCESS; | ||||
|   | ||||
| @@ -35,17 +35,21 @@ simple_system::simple_system(sc_core::sc_module_name nm) | ||||
| , NAMED(s_clk) | ||||
| , NAMED(s_rst) | ||||
| , NAMED(s_global_interrupts, 256) | ||||
| , NAMED(s_core_interrupt) { | ||||
| , NAMED(s_core_interrupt) | ||||
| , NAMED(s_gpio, 32) | ||||
| { | ||||
|     // todo: discuss naming conventions (s_<signal> vs. <port>_i/_o) --> covnert into _s | ||||
|  | ||||
|     // bus connections | ||||
|     i_master.intor(i_router.target[0]); | ||||
|     size_t i = 0; | ||||
|     for (const auto &e : e300_plat_map) { | ||||
|         i_router.initiator[i](e.target); | ||||
|         i_router.set_target_range(i, e.start, e.size); | ||||
|         i++; | ||||
|     } | ||||
|     i_router.bind_target(i_plic.socket, 0, "plic"); | ||||
|     i_router.bind_target(i_uart.socket, 1, "uart"); | ||||
|     i_router.bind_target(i_spi.socket,  2, "spi"); | ||||
|     i_router.bind_target(i_gpio.socket, 3, "gpio"); | ||||
|  | ||||
|     // target address ranges | ||||
|     for (const auto &e : e300_plat_map) | ||||
|         i_router.add_target_range(e.name, e.start, e.size); | ||||
|  | ||||
|     // clock/reset connections | ||||
|     i_uart.clk_i(s_clk); | ||||
| @@ -66,6 +70,11 @@ simple_system::simple_system(sc_core::sc_module_name nm) | ||||
|     i_master.global_interrupts_o(s_global_interrupts); | ||||
|     i_master.core_interrupt_i(s_core_interrupt); | ||||
|  | ||||
|     for(auto i=0U; i<s_gpio.size(); ++i){ | ||||
|       s_gpio[i].in(i_gpio.pins_o[i]); | ||||
|       i_gpio.pins_i[i](s_gpio[i].out); | ||||
|     } | ||||
|  | ||||
|     SC_THREAD(gen_reset); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -48,7 +48,8 @@ public: | ||||
|     sc_core::sc_signal<sc_core::sc_time> s_clk; | ||||
|     sc_core::sc_signal<bool> s_rst; | ||||
|     sc_core::sc_vector<sc_core::sc_signal<bool>> s_global_interrupts; | ||||
|     sc_core::sc_signal<bool> s_core_interrupt; | ||||
|     sc_core::sc_signal<bool, sc_core::SC_MANY_WRITERS> s_core_interrupt; | ||||
|     sc_core::sc_vector<tlm::tlm_signal<>> s_gpio; | ||||
|  | ||||
|     simple_system(sc_core::sc_module_name nm); | ||||
|  | ||||
|   | ||||
| @@ -36,8 +36,10 @@ | ||||
| #define PLIC_CLAIM_COMPLETE_REG 0x0C200004 | ||||
|  | ||||
| namespace sysc { | ||||
| test_initiator::test_initiator(sc_core::sc_module_name nm) | ||||
| : sc_core::sc_module(nm) | ||||
| using namespace sc_core; | ||||
|  | ||||
| test_initiator::test_initiator(sc_module_name nm) | ||||
| : sc_module(nm) | ||||
| , NAMED(intor) | ||||
| , NAMED(rst_i) | ||||
| , NAMED(global_interrupts_o, 256) | ||||
| @@ -62,6 +64,8 @@ void test_initiator::run() { | ||||
|     test_irq_stress(); | ||||
|  | ||||
|     // todo: review irq sequences from FW point of view ... expected ??? | ||||
|     wait(100_ns); | ||||
|     sc_stop(); | ||||
| } | ||||
|  | ||||
| void test_initiator::test_unique_irq() { | ||||
| @@ -211,14 +215,14 @@ void test_initiator::write_bus(std::uint32_t adr, std::uint32_t dat) { | ||||
|     data[1] = 0xff & dat >> 8; | ||||
|     data[0] = 0xff & dat; | ||||
|  | ||||
|     LOG(INFO) << "write_bus(0x" << std::hex << adr << ") : " << dat; | ||||
|     SCDEBUG("test_initiator") << "write_bus(0x" << std::hex << adr << ") : " << dat; | ||||
|  | ||||
|     gp.set_command(tlm::TLM_WRITE_COMMAND); | ||||
|     gp.set_address(adr); | ||||
|     gp.set_data_ptr(data.data()); | ||||
|     gp.set_data_length(data.size()); | ||||
|     gp.set_streaming_width(4); | ||||
|     sc_core::sc_time delay; | ||||
|     sc_time delay; | ||||
|     intor->b_transport(gp, delay); | ||||
|  | ||||
|     if (gp.get_response_status() != tlm::TLM_OK_RESPONSE) { | ||||
| @@ -236,7 +240,7 @@ std::uint32_t test_initiator::read_bus(std::uint32_t adr) { | ||||
|     gp.set_data_ptr(data.data()); | ||||
|     gp.set_data_length(data.size()); | ||||
|     gp.set_streaming_width(4); | ||||
|     sc_core::sc_time delay; | ||||
|     sc_time delay; | ||||
|     intor->b_transport(gp, delay); | ||||
|  | ||||
|     if (gp.get_response_status() != tlm::TLM_OK_RESPONSE) { | ||||
| @@ -248,21 +252,21 @@ std::uint32_t test_initiator::read_bus(std::uint32_t adr) { | ||||
|     // todo: use reinterpret_cast instead | ||||
|     std::uint32_t rdat = data[3] << 24 | data[2] << 16 | data[1] << 8 | data[0]; | ||||
|  | ||||
|     LOG(INFO) << "read_bus(0x" << std::hex << adr << ") -> " << rdat; | ||||
|     SCDEBUG("test_initiator") << "read_bus(0x" << std::hex << adr << ") -> " << rdat; | ||||
|     return rdat; | ||||
| } | ||||
|  | ||||
| void test_initiator::reg_check(std::uint32_t adr, std::uint32_t exp) { | ||||
|     uint32_t dat = read_bus(adr); | ||||
|     if (dat != exp) { | ||||
|         LOG(ERROR) << "register check failed for address 0x" << std::hex << adr << ": " << dat << " !=  " << exp; | ||||
|         SCERR("test_initiator") << "register check failed for address 0x" << std::hex << adr << ": " << dat << " !=  " << exp; | ||||
|     } else { | ||||
|         LOG(INFO) << "register check passed for address 0x" << std::hex << adr << ": " << dat; | ||||
|         SCDEBUG("test_initiator") << "register check passed for address 0x" << std::hex << adr << ": " << dat; | ||||
|     } | ||||
| } | ||||
|  | ||||
| void test_initiator::core_irq_handler() { | ||||
|     LOG(INFO) << "core_interrupt_i edge detected -> " << core_interrupt_i.read(); | ||||
|     SCDEBUG("test_initiator") << "core_interrupt_i edge detected -> " << core_interrupt_i.read(); | ||||
| } | ||||
|  | ||||
| } /* namespace sysc */ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user