cleans up project and adds axi4_pin_level test
This commit is contained in:
		| @@ -1,8 +0,0 @@ | ||||
| cmake_minimum_required(VERSION 3.12) | ||||
|  | ||||
| if(SCV_FOUND)    | ||||
|     add_subdirectory(transaction_recording) | ||||
| endif() | ||||
|  | ||||
| add_subdirectory(simple_system) | ||||
| add_subdirectory(ahb_bfm) | ||||
| @@ -1,10 +0,0 @@ | ||||
| cmake_minimum_required(VERSION 3.3) | ||||
| # Add executable called "transaction_recording" that is built from the source files | ||||
| # "scv_tr_recording_example.cpp". The extensions are automatically found. | ||||
| add_executable (ahb_bfm | ||||
| 	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 | ||||
| # transaction_recording | ||||
| target_link_libraries (ahb_bfm LINK_PUBLIC scc) | ||||
| @@ -1,145 +0,0 @@ | ||||
| #include <ahb/pin/initiator.h> | ||||
| #include <ahb/pin/target.h> | ||||
| #include <tlm/scc/initiator_mixin.h> | ||||
| #include <tlm/scc/target_mixin.h> | ||||
| #include <scc/configurable_tracer.h> | ||||
| #include <scc/configurer.h> | ||||
| #include <scc/report.h> | ||||
| #include <scc/tracer.h> | ||||
| #include <scc/traceable.h> | ||||
| #include <cci_utils/broker.h> | ||||
| #include <fstream> | ||||
|  | ||||
| using namespace sc_core; | ||||
| using namespace scc; | ||||
|  | ||||
| class testbench: public sc_module, public scc::traceable { | ||||
| public: | ||||
|     enum { WIDTH=64}; | ||||
|     tlm::scc::initiator_mixin<tlm::tlm_initiator_socket<WIDTH>> isck{"isck"}; | ||||
|     ahb::pin::initiator<WIDTH> intor{"intor"}; | ||||
|     sc_core::sc_clock                         HCLK{"HCLK", 10_ns}; | ||||
|     sc_core::sc_signal<bool>                  HRESETn{"HRESETn"}; | ||||
|     sc_core::sc_signal<sc_dt::sc_uint<32>>    HADDR{"HADDR"}; | ||||
|     sc_core::sc_signal<sc_dt::sc_uint<3>>     HBURST{"HBURST"}; | ||||
|     sc_core::sc_signal<bool>                  HMASTLOCK{"HMASTLOCK"}; | ||||
|     sc_core::sc_signal<sc_dt::sc_uint<4>>     HPROT{"HPROT"}; | ||||
|     sc_core::sc_signal<sc_dt::sc_uint<3>>     HSIZE{"HSIZE"}; | ||||
|     sc_core::sc_signal<sc_dt::sc_uint<2>>     HTRANS{"HTRANS"}; | ||||
|     sc_core::sc_signal<sc_dt::sc_uint<WIDTH>> HWDATA{"HWDATA"}; | ||||
|     sc_core::sc_signal<bool>                  HWRITE{"HWRITE"}; | ||||
|     sc_core::sc_signal<sc_dt::sc_uint<WIDTH>>  HRDATA{"HRDATA"}; | ||||
|     sc_core::sc_signal<bool>                   HREADY{"HREADY"}; | ||||
|     sc_core::sc_signal<bool>                   HRESP{"HRESP"}; | ||||
|     sc_core::sc_signal<bool>                   HSEL{"HSEL"}; | ||||
|  | ||||
|     ahb::pin::target<WIDTH> target{"target"}; | ||||
|     tlm::scc::target_mixin<tlm::tlm_target_socket<WIDTH>> tsck{"tsck"}; | ||||
|  | ||||
|     testbench(sc_module_name nm):sc_module(nm){ | ||||
|         SC_HAS_PROCESS(testbench); | ||||
|         isck(intor.tsckt); | ||||
|         intor.HCLK_i(HCLK); | ||||
|         intor.HRESETn_i(HRESETn); | ||||
|         intor.HADDR_o(HADDR); | ||||
|         intor.HBURST_o(HBURST); | ||||
|         intor.HMASTLOCK_o(HMASTLOCK); | ||||
|         intor.HPROT_o(HPROT); | ||||
|         intor.HSIZE_o(HSIZE); | ||||
|         intor.HTRANS_o(HTRANS); | ||||
|         intor.HWDATA_o(HWDATA); | ||||
|         intor.HWRITE_o(HWRITE); | ||||
|         intor.HRDATA_i(HRDATA); | ||||
|         intor.HREADY_i(HREADY); | ||||
|         intor.HRESP_i(HRESP); | ||||
|         target.HCLK_i(HCLK); | ||||
|         target.HRESETn_i(HRESETn); | ||||
|         target.HADDR_i(HADDR); | ||||
|         target.HBURST_i(HBURST); | ||||
|         target.HMASTLOCK_i(HMASTLOCK); | ||||
|         target.HPROT_i(HPROT); | ||||
|         target.HSIZE_i(HSIZE); | ||||
|         target.HTRANS_i(HTRANS); | ||||
|         target.HWDATA_i(HWDATA); | ||||
|         target.HWRITE_i(HWRITE); | ||||
|         target.HSEL_i(HSEL); | ||||
|         target.HRDATA_o(HRDATA); | ||||
|         target.HREADY_o(HREADY); | ||||
|         target.HRESP_o(HRESP); | ||||
|         target.isckt(tsck); | ||||
|         SC_THREAD(run); | ||||
|         tsck.register_b_transport([this](tlm::tlm_generic_payload& gp, sc_time& delay){ | ||||
|             gp.set_response_status(tlm::TLM_OK_RESPONSE); | ||||
|             if(gp.is_write()){ | ||||
|                 SCCINFO(SCMOD)<<"Received write access to addr 0x"<<std::hex<<gp.get_address(); | ||||
|             } else{ | ||||
|                 memset(gp.get_data_ptr(), 0x55, gp.get_data_length()); | ||||
|                 SCCINFO(SCMOD)<<"Received read access from addr 0x"<<std::hex<<gp.get_address(); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     void run(){ | ||||
|         HRESETn.write(false); | ||||
|         for(size_t i=0; i<10; ++i) wait(HCLK.posedge_event()); | ||||
|         HRESETn.write(true); | ||||
|         wait(HCLK.posedge_event()); | ||||
|         HSEL.write(true); | ||||
|         tlm::tlm_generic_payload gp; | ||||
|         std::array<uint8_t, 8> data; | ||||
|         data[0]=2; | ||||
|         data[1]=4; | ||||
|         gp.set_address(0x1000); | ||||
|         gp.set_data_length(8); | ||||
|         gp.set_data_ptr(data.data()); | ||||
|         gp.set_streaming_width(8); | ||||
|         gp.set_command(tlm::TLM_WRITE_COMMAND); | ||||
|         sc_time delay; | ||||
|         isck->b_transport(gp, delay); | ||||
|         gp.set_address(0x1020); | ||||
|         gp.set_data_length(8); | ||||
|         gp.set_data_ptr(data.data()); | ||||
|         gp.set_streaming_width(8); | ||||
|         gp.set_command(tlm::TLM_READ_COMMAND); | ||||
|         delay=SC_ZERO_TIME; | ||||
|         isck->b_transport(gp, delay); | ||||
|         for(size_t i=0; i<10; ++i) wait(HCLK.posedge_event()); | ||||
|         sc_stop(); | ||||
|     } | ||||
|  | ||||
| }; | ||||
|  | ||||
| int sc_main (int argc , char *argv[]){ | ||||
|     sc_core::sc_report_handler::set_actions( "/IEEE_Std_1666/deprecated", sc_core::SC_DO_NOTHING ); | ||||
|     sc_report_handler::set_actions(SC_ID_MORE_THAN_ONE_SIGNAL_DRIVER_, SC_DO_NOTHING); | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     // configure logging | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     scc::init_logging(scc::log::DEBUG); | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     // set up configuration and tracing | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     scc::configurer cfg("ahb_bfm.json"); | ||||
|     scc::configurable_tracer trace("ahb_bfm", tracer::TEXT, true, true); | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     // create modules/channels and trace | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     testbench tb("tb"); | ||||
|     trace.add_control(); | ||||
|     { | ||||
|         std::ofstream of{"ahb_test.default.json"}; | ||||
|         if (of.is_open()) cfg.dump_configuration(of); | ||||
|     } | ||||
|     cfg.configure(); | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     // run the simulation | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     try { | ||||
|         sc_core::sc_start(1_us); | ||||
|         if (!sc_core::sc_end_of_simulation_invoked()) sc_core::sc_stop(); | ||||
|     } catch (sc_core::sc_report &rep) { | ||||
|         sc_core::sc_report_handler::get_handler()(rep, sc_core::SC_DISPLAY | sc_core::SC_STOP); | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| @@ -1,18 +0,0 @@ | ||||
| cmake_minimum_required(VERSION 3.12) | ||||
| find_package(Boost COMPONENTS program_options REQUIRED) | ||||
| add_executable (simple_system  | ||||
|     plic.cpp | ||||
|     uart.cpp | ||||
|     spi.cpp | ||||
|     gpio.cpp | ||||
|     test_initiator.cpp | ||||
|     simple_system.cpp | ||||
|     sc_main.cpp | ||||
| ) | ||||
| target_link_libraries (simple_system LINK_PUBLIC scc) | ||||
| if(TARGET Boost::program_options) | ||||
| 	target_link_libraries(simple_system PUBLIC Boost::program_options) | ||||
| else() | ||||
| 	target_link_libraries(simple_system PUBLIC ${BOOST_program_options_LIBRARY}) | ||||
| endif() | ||||
| add_test(NAME simple_system_test COMMAND simple_system) | ||||
| @@ -1,27 +0,0 @@ | ||||
| /******************************************************************************* | ||||
|  * 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. | ||||
|  ******************************************************************************/ | ||||
| #ifndef _E300_PLAT_MAP_H_ | ||||
| #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_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_ */ | ||||
| @@ -1,152 +0,0 @@ | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| // 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. | ||||
| // | ||||
| // Created on: Wed Sep 20 11:47:24 CEST 2017 | ||||
| //             *      gpio_regs.h Author: <RDL Generator> | ||||
| // | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| #ifndef _GPIO_REGS_H_ | ||||
| #define _GPIO_REGS_H_ | ||||
|  | ||||
| #include <util/bit_field.h> | ||||
| #include "scc/register.h" | ||||
| #include "scc/tlm_target.h" | ||||
| #include "scc/utilities.h" | ||||
|  | ||||
| namespace sysc { | ||||
|  | ||||
| class gpio_regs : public sc_core::sc_module, public scc::resetable { | ||||
| public: | ||||
|     // storage declarations | ||||
|     uint32_t r_value; | ||||
|  | ||||
|     uint32_t r_input_en; | ||||
|  | ||||
|     uint32_t r_output_en; | ||||
|  | ||||
|     uint32_t r_port; | ||||
|  | ||||
|     uint32_t r_pue; | ||||
|  | ||||
|     uint32_t r_ds; | ||||
|  | ||||
|     uint32_t r_rise_ie; | ||||
|  | ||||
|     uint32_t r_rise_ip; | ||||
|  | ||||
|     uint32_t r_fall_ie; | ||||
|  | ||||
|     uint32_t r_fall_ip; | ||||
|  | ||||
|     uint32_t r_high_ie; | ||||
|  | ||||
|     uint32_t r_high_ip; | ||||
|  | ||||
|     uint32_t r_low_ie; | ||||
|  | ||||
|     uint32_t r_low_ip; | ||||
|  | ||||
|     uint32_t r_iof_en; | ||||
|  | ||||
|     uint32_t r_iof_sel; | ||||
|  | ||||
|     uint32_t r_out_xor; | ||||
|  | ||||
|     // register declarations | ||||
|     scc::sc_register<uint32_t> value; | ||||
|     scc::sc_register<uint32_t> input_en; | ||||
|     scc::sc_register<uint32_t> output_en; | ||||
|     scc::sc_register<uint32_t> port; | ||||
|     scc::sc_register<uint32_t> pue; | ||||
|     scc::sc_register<uint32_t> ds; | ||||
|     scc::sc_register<uint32_t> rise_ie; | ||||
|     scc::sc_register<uint32_t> rise_ip; | ||||
|     scc::sc_register<uint32_t> fall_ie; | ||||
|     scc::sc_register<uint32_t> fall_ip; | ||||
|     scc::sc_register<uint32_t> high_ie; | ||||
|     scc::sc_register<uint32_t> high_ip; | ||||
|     scc::sc_register<uint32_t> low_ie; | ||||
|     scc::sc_register<uint32_t> low_ip; | ||||
|     scc::sc_register<uint32_t> iof_en; | ||||
|     scc::sc_register<uint32_t> iof_sel; | ||||
|     scc::sc_register<uint32_t> out_xor; | ||||
|  | ||||
| public: | ||||
|     gpio_regs(sc_core::sc_module_name nm); | ||||
|  | ||||
|     template <unsigned BUSWIDTH = 32> void registerResources(scc::tlm_target<BUSWIDTH> &target); | ||||
| }; | ||||
| } | ||||
| ////////////////////////////////////////////////////////////////////////////// | ||||
| // member functions | ||||
| ////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| inline sysc::gpio_regs::gpio_regs(sc_core::sc_module_name nm) | ||||
| : sc_core::sc_module(nm) | ||||
| , NAMED(value, r_value, 0, *this) | ||||
| , NAMED(input_en, r_input_en, 0, *this) | ||||
| , NAMED(output_en, r_output_en, 0, *this) | ||||
| , NAMED(port, r_port, 0, *this) | ||||
| , NAMED(pue, r_pue, 0, *this) | ||||
| , NAMED(ds, r_ds, 0, *this) | ||||
| , NAMED(rise_ie, r_rise_ie, 0, *this) | ||||
| , NAMED(rise_ip, r_rise_ip, 0, *this) | ||||
| , NAMED(fall_ie, r_fall_ie, 0, *this) | ||||
| , NAMED(fall_ip, r_fall_ip, 0, *this) | ||||
| , NAMED(high_ie, r_high_ie, 0, *this) | ||||
| , NAMED(high_ip, r_high_ip, 0, *this) | ||||
| , NAMED(low_ie, r_low_ie, 0, *this) | ||||
| , NAMED(low_ip, r_low_ip, 0, *this) | ||||
| , NAMED(iof_en, r_iof_en, 0, *this) | ||||
| , NAMED(iof_sel, r_iof_sel, 0, *this) | ||||
| , NAMED(out_xor, r_out_xor, 0, *this) {} | ||||
|  | ||||
| template <unsigned BUSWIDTH> inline void sysc::gpio_regs::registerResources(scc::tlm_target<BUSWIDTH> &target) { | ||||
|     target.addResource(value, 0x0UL); | ||||
|     target.addResource(input_en, 0x4UL); | ||||
|     target.addResource(output_en, 0x8UL); | ||||
|     target.addResource(port, 0xcUL); | ||||
|     target.addResource(pue, 0x10UL); | ||||
|     target.addResource(ds, 0x14UL); | ||||
|     target.addResource(rise_ie, 0x18UL); | ||||
|     target.addResource(rise_ip, 0x1cUL); | ||||
|     target.addResource(fall_ie, 0x20UL); | ||||
|     target.addResource(fall_ip, 0x24UL); | ||||
|     target.addResource(high_ie, 0x28UL); | ||||
|     target.addResource(high_ip, 0x2cUL); | ||||
|     target.addResource(low_ie, 0x30UL); | ||||
|     target.addResource(low_ip, 0x34UL); | ||||
|     target.addResource(iof_en, 0x38UL); | ||||
|     target.addResource(iof_sel, 0x3cUL); | ||||
|     target.addResource(out_xor, 0x40UL); | ||||
| } | ||||
|  | ||||
| #endif // _GPIO_REGS_H_ | ||||
| @@ -1,96 +0,0 @@ | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| // 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. | ||||
| // | ||||
| // Created on: Wed Sep 20 22:30:45 CEST 2017 | ||||
| //             *      plic_regs.h Author: <RDL Generator> | ||||
| // | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| #ifndef _PLIC_REGS_H_ | ||||
| #define _PLIC_REGS_H_ | ||||
|  | ||||
| #include <util/bit_field.h> | ||||
| #include "scc/register.h" | ||||
| #include "scc/tlm_target.h" | ||||
| #include "scc/utilities.h" | ||||
|  | ||||
| namespace sysc { | ||||
|  | ||||
| class plic_regs : public sc_core::sc_module, public scc::resetable { | ||||
| public: | ||||
|     // storage declarations | ||||
|     BEGIN_BF_DECL(priority_t, uint32_t); | ||||
|     BF_FIELD(priority, 0, 3); | ||||
|     END_BF_DECL(); | ||||
|     std::array<priority_t, 255> r_priority; | ||||
|  | ||||
|     uint32_t r_pending; | ||||
|  | ||||
|     uint32_t r_enabled; | ||||
|  | ||||
|     BEGIN_BF_DECL(threshold_t, uint32_t); | ||||
|     BF_FIELD(threshold, 0, 3); | ||||
|     END_BF_DECL() r_threshold; | ||||
|  | ||||
|     uint32_t r_claim_complete; | ||||
|  | ||||
|     // register declarations | ||||
|     scc::sc_register_indexed<priority_t, 255> priority; | ||||
|     scc::sc_register<uint32_t> pending; | ||||
|     scc::sc_register<uint32_t> enabled; | ||||
|     scc::sc_register<threshold_t> threshold; | ||||
|     scc::sc_register<uint32_t> claim_complete; | ||||
|  | ||||
|     plic_regs(sc_core::sc_module_name nm); | ||||
|  | ||||
|     template <unsigned BUSWIDTH = 32> void registerResources(scc::tlm_target<BUSWIDTH> &target); | ||||
| }; | ||||
| } | ||||
| ////////////////////////////////////////////////////////////////////////////// | ||||
| // member functions | ||||
| ////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| inline sysc::plic_regs::plic_regs(sc_core::sc_module_name nm) | ||||
| : sc_core::sc_module(nm) | ||||
| , NAMED(priority, r_priority, 0, *this) | ||||
| , NAMED(pending, r_pending, 0, *this) | ||||
| , NAMED(enabled, r_enabled, 0, *this) | ||||
| , NAMED(threshold, r_threshold, 0, *this) | ||||
| , NAMED(claim_complete, r_claim_complete, 0, *this) {} | ||||
|  | ||||
| template <unsigned BUSWIDTH> inline void sysc::plic_regs::registerResources(scc::tlm_target<BUSWIDTH> &target) { | ||||
|     target.addResource(priority, 0x4UL); | ||||
|     target.addResource(pending, 0x1000UL); | ||||
|     target.addResource(enabled, 0x2000UL); | ||||
|     target.addResource(threshold, 0x00200000UL); | ||||
|     target.addResource(claim_complete, 0x00200004UL); | ||||
| } | ||||
|  | ||||
| #endif // _PLIC_REGS_H_ | ||||
| @@ -1,192 +0,0 @@ | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| // 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. | ||||
| // | ||||
| // Created on: Wed Sep 20 22:30:45 CEST 2017 | ||||
| //             *      spi_regs.h Author: <RDL Generator> | ||||
| // | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| #ifndef _SPI_REGS_H_ | ||||
| #define _SPI_REGS_H_ | ||||
|  | ||||
| #include <util/bit_field.h> | ||||
| #include "scc/register.h" | ||||
| #include "scc/tlm_target.h" | ||||
| #include "scc/utilities.h" | ||||
|  | ||||
| namespace sysc { | ||||
|  | ||||
| class spi_regs : public sc_core::sc_module, public scc::resetable { | ||||
| protected: | ||||
|     // storage declarations | ||||
|     BEGIN_BF_DECL(sckdiv_t, uint32_t); | ||||
|     BF_FIELD(div, 0, 12); | ||||
|     END_BF_DECL() r_sckdiv; | ||||
|  | ||||
|     BEGIN_BF_DECL(sckmode_t, uint32_t); | ||||
|     BF_FIELD(pha, 0, 1); | ||||
|     BF_FIELD(pol, 1, 1); | ||||
|     END_BF_DECL() r_sckmode; | ||||
|  | ||||
|     uint32_t r_csid; | ||||
|  | ||||
|     uint32_t r_csdef; | ||||
|  | ||||
|     BEGIN_BF_DECL(csmode_t, uint32_t); | ||||
|     BF_FIELD(mode, 0, 2); | ||||
|     END_BF_DECL() r_csmode; | ||||
|  | ||||
|     BEGIN_BF_DECL(delay0_t, uint32_t); | ||||
|     BF_FIELD(cssck, 0, 8); | ||||
|     BF_FIELD(sckcs, 16, 8); | ||||
|     END_BF_DECL() r_delay0; | ||||
|  | ||||
|     BEGIN_BF_DECL(delay1_t, uint32_t); | ||||
|     BF_FIELD(intercs, 0, 16); | ||||
|     BF_FIELD(interxfr, 16, 8); | ||||
|     END_BF_DECL() r_delay1; | ||||
|  | ||||
|     BEGIN_BF_DECL(fmt_t, uint32_t); | ||||
|     BF_FIELD(proto, 0, 2); | ||||
|     BF_FIELD(endian, 2, 1); | ||||
|     BF_FIELD(dir, 3, 1); | ||||
|     BF_FIELD(len, 16, 4); | ||||
|     END_BF_DECL() r_fmt; | ||||
|  | ||||
|     BEGIN_BF_DECL(txdata_t, uint32_t); | ||||
|     BF_FIELD(data, 0, 8); | ||||
|     BF_FIELD(full, 31, 1); | ||||
|     END_BF_DECL() r_txdata; | ||||
|  | ||||
|     BEGIN_BF_DECL(rxdata_t, uint32_t); | ||||
|     BF_FIELD(data, 0, 8); | ||||
|     BF_FIELD(empty, 31, 1); | ||||
|     END_BF_DECL() r_rxdata; | ||||
|  | ||||
|     BEGIN_BF_DECL(txmark_t, uint32_t); | ||||
|     BF_FIELD(txmark, 0, 3); | ||||
|     END_BF_DECL() r_txmark; | ||||
|  | ||||
|     BEGIN_BF_DECL(rxmark_t, uint32_t); | ||||
|     BF_FIELD(rxmark, 0, 3); | ||||
|     END_BF_DECL() r_rxmark; | ||||
|  | ||||
|     BEGIN_BF_DECL(fctrl_t, uint32_t); | ||||
|     BF_FIELD(en, 0, 1); | ||||
|     END_BF_DECL() r_fctrl; | ||||
|  | ||||
|     BEGIN_BF_DECL(ffmt_t, uint32_t); | ||||
|     BF_FIELD(cmd_en, 0, 1); | ||||
|     BF_FIELD(addr_len, 1, 2); | ||||
|     BF_FIELD(pad_cnt, 3, 4); | ||||
|     BF_FIELD(cmd_proto, 7, 2); | ||||
|     BF_FIELD(addr_proto, 9, 2); | ||||
|     BF_FIELD(data_proto, 11, 2); | ||||
|     BF_FIELD(cmd_code, 16, 8); | ||||
|     BF_FIELD(pad_code, 24, 8); | ||||
|     END_BF_DECL() r_ffmt; | ||||
|  | ||||
|     BEGIN_BF_DECL(ie_t, uint32_t); | ||||
|     BF_FIELD(txwm, 0, 1); | ||||
|     BF_FIELD(rxwm, 1, 1); | ||||
|     END_BF_DECL() r_ie; | ||||
|  | ||||
|     BEGIN_BF_DECL(ip_t, uint32_t); | ||||
|     BF_FIELD(txwm, 0, 1); | ||||
|     BF_FIELD(rxwm, 1, 1); | ||||
|     END_BF_DECL() r_ip; | ||||
|  | ||||
|     // register declarations | ||||
|     scc::sc_register<sckdiv_t> sckdiv; | ||||
|     scc::sc_register<sckmode_t> sckmode; | ||||
|     scc::sc_register<uint32_t> csid; | ||||
|     scc::sc_register<uint32_t> csdef; | ||||
|     scc::sc_register<csmode_t> csmode; | ||||
|     scc::sc_register<delay0_t> delay0; | ||||
|     scc::sc_register<delay1_t> delay1; | ||||
|     scc::sc_register<fmt_t> fmt; | ||||
|     scc::sc_register<txdata_t> txdata; | ||||
|     scc::sc_register<rxdata_t> rxdata; | ||||
|     scc::sc_register<txmark_t> txmark; | ||||
|     scc::sc_register<rxmark_t> rxmark; | ||||
|     scc::sc_register<fctrl_t> fctrl; | ||||
|     scc::sc_register<ffmt_t> ffmt; | ||||
|     scc::sc_register<ie_t> ie; | ||||
|     scc::sc_register<ip_t> ip; | ||||
|  | ||||
| public: | ||||
|     spi_regs(sc_core::sc_module_name nm); | ||||
|  | ||||
|     template <unsigned BUSWIDTH = 32> void registerResources(scc::tlm_target<BUSWIDTH> &target); | ||||
| }; | ||||
| } | ||||
| ////////////////////////////////////////////////////////////////////////////// | ||||
| // member functions | ||||
| ////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| inline sysc::spi_regs::spi_regs(sc_core::sc_module_name nm) | ||||
| : sc_core::sc_module(nm) | ||||
| , NAMED(sckdiv, r_sckdiv, 0, *this) | ||||
| , NAMED(sckmode, r_sckmode, 0, *this) | ||||
| , NAMED(csid, r_csid, 0, *this) | ||||
| , NAMED(csdef, r_csdef, 0, *this) | ||||
| , NAMED(csmode, r_csmode, 0, *this) | ||||
| , NAMED(delay0, r_delay0, 0, *this) | ||||
| , NAMED(delay1, r_delay1, 0, *this) | ||||
| , NAMED(fmt, r_fmt, 0, *this) | ||||
| , NAMED(txdata, r_txdata, 0, *this) | ||||
| , NAMED(rxdata, r_rxdata, 0, *this) | ||||
| , NAMED(txmark, r_txmark, 0, *this) | ||||
| , NAMED(rxmark, r_rxmark, 0, *this) | ||||
| , NAMED(fctrl, r_fctrl, 0, *this) | ||||
| , NAMED(ffmt, r_ffmt, 0, *this) | ||||
| , NAMED(ie, r_ie, 0, *this) | ||||
| , NAMED(ip, r_ip, 0, *this) {} | ||||
|  | ||||
| template <unsigned BUSWIDTH> inline void sysc::spi_regs::registerResources(scc::tlm_target<BUSWIDTH> &target) { | ||||
|     target.addResource(sckdiv, 0x0UL); | ||||
|     target.addResource(sckmode, 0x4UL); | ||||
|     target.addResource(csid, 0x10UL); | ||||
|     target.addResource(csdef, 0x14UL); | ||||
|     target.addResource(csmode, 0x18UL); | ||||
|     target.addResource(delay0, 0x28UL); | ||||
|     target.addResource(delay1, 0x2cUL); | ||||
|     target.addResource(fmt, 0x40UL); | ||||
|     target.addResource(txdata, 0x48UL); | ||||
|     target.addResource(rxdata, 0x4cUL); | ||||
|     target.addResource(txmark, 0x50UL); | ||||
|     target.addResource(rxmark, 0x54UL); | ||||
|     target.addResource(fctrl, 0x60UL); | ||||
|     target.addResource(ffmt, 0x64UL); | ||||
|     target.addResource(ie, 0x70UL); | ||||
|     target.addResource(ip, 0x74UL); | ||||
| } | ||||
|  | ||||
| #endif // _SPI_REGS_H_ | ||||
| @@ -1,125 +0,0 @@ | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| // 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. | ||||
| // | ||||
| // Created on: Wed Sep 20 22:30:45 CEST 2017 | ||||
| //             *      uart_regs.h Author: <RDL Generator> | ||||
| // | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| #ifndef _UART_REGS_H_ | ||||
| #define _UART_REGS_H_ | ||||
|  | ||||
| #include <util/bit_field.h> | ||||
| #include "scc/register.h" | ||||
| #include "scc/tlm_target.h" | ||||
| #include "scc/utilities.h" | ||||
|  | ||||
| namespace sysc { | ||||
|  | ||||
| class uart_regs : public sc_core::sc_module, public scc::resetable { | ||||
| protected: | ||||
|     // storage declarations | ||||
|     BEGIN_BF_DECL(txdata_t, uint32_t); | ||||
|     BF_FIELD(data, 0, 8); | ||||
|     BF_FIELD(full, 31, 1); | ||||
|     END_BF_DECL() r_txdata; | ||||
|  | ||||
|     BEGIN_BF_DECL(rxdata_t, uint32_t); | ||||
|     BF_FIELD(data, 0, 8); | ||||
|     BF_FIELD(empty, 31, 1); | ||||
|     END_BF_DECL() r_rxdata; | ||||
|  | ||||
|     BEGIN_BF_DECL(txctrl_t, uint32_t); | ||||
|     BF_FIELD(txen, 0, 1); | ||||
|     BF_FIELD(nstop, 1, 1); | ||||
|     BF_FIELD(reserved, 2, 14); | ||||
|     BF_FIELD(txcnt, 16, 3); | ||||
|     END_BF_DECL() r_txctrl; | ||||
|  | ||||
|     BEGIN_BF_DECL(rxctrl_t, uint32_t); | ||||
|     BF_FIELD(rxen, 0, 1); | ||||
|     BF_FIELD(reserved, 1, 15); | ||||
|     BF_FIELD(rxcnt, 16, 3); | ||||
|     END_BF_DECL() r_rxctrl; | ||||
|  | ||||
|     BEGIN_BF_DECL(ie_t, uint32_t); | ||||
|     BF_FIELD(txwm, 0, 1); | ||||
|     BF_FIELD(rxwm, 1, 1); | ||||
|     END_BF_DECL() r_ie; | ||||
|  | ||||
|     BEGIN_BF_DECL(ip_t, uint32_t); | ||||
|     BF_FIELD(txwm, 0, 1); | ||||
|     BF_FIELD(rxwm, 1, 1); | ||||
|     END_BF_DECL() r_ip; | ||||
|  | ||||
|     BEGIN_BF_DECL(div_t, uint32_t); | ||||
|     BF_FIELD(div, 0, 16); | ||||
|     END_BF_DECL() r_div; | ||||
|  | ||||
|     // register declarations | ||||
|     scc::sc_register<txdata_t> txdata; | ||||
|     scc::sc_register<rxdata_t> rxdata; | ||||
|     scc::sc_register<txctrl_t> txctrl; | ||||
|     scc::sc_register<rxctrl_t> rxctrl; | ||||
|     scc::sc_register<ie_t> ie; | ||||
|     scc::sc_register<ip_t> ip; | ||||
|     scc::sc_register<div_t> div; | ||||
|  | ||||
| public: | ||||
|     uart_regs(sc_core::sc_module_name nm); | ||||
|  | ||||
|     template <unsigned BUSWIDTH = 32> void registerResources(scc::tlm_target<BUSWIDTH> &target); | ||||
| }; | ||||
| } | ||||
| ////////////////////////////////////////////////////////////////////////////// | ||||
| // member functions | ||||
| ////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| inline sysc::uart_regs::uart_regs(sc_core::sc_module_name nm) | ||||
| : sc_core::sc_module(nm) | ||||
| , NAMED(txdata, r_txdata, 0, *this) | ||||
| , NAMED(rxdata, r_rxdata, 0, *this) | ||||
| , NAMED(txctrl, r_txctrl, 0, *this) | ||||
| , NAMED(rxctrl, r_rxctrl, 0, *this) | ||||
| , NAMED(ie, r_ie, 0, *this) | ||||
| , NAMED(ip, r_ip, 0, *this) | ||||
| , NAMED(div, r_div, 0, *this) {} | ||||
|  | ||||
| template <unsigned BUSWIDTH> inline void sysc::uart_regs::registerResources(scc::tlm_target<BUSWIDTH> &target) { | ||||
|     target.addResource(txdata, 0x0UL); | ||||
|     target.addResource(rxdata, 0x4UL); | ||||
|     target.addResource(txctrl, 0x8UL); | ||||
|     target.addResource(rxctrl, 0xcUL); | ||||
|     target.addResource(ie, 0x10UL); | ||||
|     target.addResource(ip, 0x14UL); | ||||
|     target.addResource(div, 0x18UL); | ||||
| } | ||||
|  | ||||
| #endif // _UART_REGS_H_ | ||||
| @@ -1,220 +0,0 @@ | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| // 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 | ||||
| // | ||||
| // | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| #include "gpio.h" | ||||
| #include "scc/report.h" | ||||
| #include "scc/utilities.h" | ||||
| #include "gen/gpio_regs.h" | ||||
| #include <limits> | ||||
|  | ||||
| namespace sysc { | ||||
|  | ||||
| using namespace sc_core; | ||||
|  | ||||
| gpio::gpio(sc_module_name nm) | ||||
| : sc_module(nm) | ||||
| , tlm_target<>(clk) | ||||
| , NAMED(clk_i) | ||||
| , NAMED(rst_i) | ||||
| , 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::scc::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::scc::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::scc::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() = default; | ||||
|  | ||||
| void gpio::reset_cb() { | ||||
|     if (rst_i.read()){ | ||||
|         regs->reset_start(); | ||||
|     } 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::scc::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::scc::tlm_signal_gp<bool> gp; | ||||
|     bool val{false}; | ||||
|     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::scc::tlm_signal_gp<bool>& gp, sc_time& delay) { | ||||
|     if(delay>SC_ZERO_TIME){ | ||||
|         wait(delay); | ||||
|         delay=SC_ZERO_TIME; | ||||
|     } | ||||
|     auto mask = 1u<<tag; | ||||
|     if((regs->r_output_en&mask)==0){ | ||||
|         if(gp.get_value()) | ||||
|             regs->r_value|=mask; | ||||
|         else | ||||
|             regs->r_value&=~mask; | ||||
|         forward_pin_input(tag, gp); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void gpio::forward_pin_input(unsigned int tag, tlm::scc::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::scc::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::scc::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::scc::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,86 +0,0 @@ | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| // 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 "tlm/scc/signal_target_mixin.h" | ||||
| #include "tlm/scc/signal_initiator_mixin.h" | ||||
| #include <tlm/scc/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<tlm::scc::tlm_signal_bool_out> pins_o; | ||||
|     sc_core::sc_vector<tlm::scc::tlm_signal_bool_in>  pins_i; | ||||
|  | ||||
|     sc_core::sc_vector<tlm::scc::tlm_signal_bool_opt_out> iof0_o; | ||||
|     sc_core::sc_vector<tlm::scc::tlm_signal_bool_opt_out> iof1_o; | ||||
|     sc_core::sc_vector<tlm::scc::tlm_signal_bool_opt_in>  iof0_i; | ||||
|     sc_core::sc_vector<tlm::scc::tlm_signal_bool_opt_in>  iof1_i; | ||||
|  | ||||
|     gpio(sc_core::sc_module_name nm); | ||||
|     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::scc::tlm_signal_gp<>& gp, sc_core::sc_time& delay); | ||||
|     void forward_pin_input(unsigned int tag, tlm::scc::tlm_signal_gp<>& gp); | ||||
|     void iof_input(unsigned int tag, unsigned iof_idx, tlm::scc::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::scc::tlm_signal_gp<>& gp, size_t i, bool val); | ||||
| }; | ||||
|  | ||||
| } /* namespace sysc */ | ||||
|  | ||||
| #endif /* _GPIO_H_ */ | ||||
| @@ -1,177 +0,0 @@ | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| // 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 LIABILITY0x200004, 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 API and implementation | ||||
| // | ||||
| // | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| // todo: truncate values beyond 7 (in prio_threshold write_cb) | ||||
|  | ||||
| #include "plic.h" | ||||
| #include "gen/plic_regs.h" | ||||
| #include "scc/utilities.h" | ||||
| #include <scc/report.h> | ||||
|  | ||||
| namespace sysc { | ||||
|  | ||||
| plic::plic(sc_core::sc_module_name nm) | ||||
| : sc_core::sc_module(nm) | ||||
| , tlm_target<>(clk) | ||||
| , NAMED(clk_i) | ||||
| , NAMED(rst_i) | ||||
| , NAMED(global_interrupts_i, 256) | ||||
| , NAMED(core_interrupt_o) | ||||
| , NAMEDD(regs, plic_regs) | ||||
| { | ||||
|     regs->registerResources(*this); | ||||
|     // register callbacks | ||||
|     init_callbacks(); | ||||
|     regs->claim_complete.set_write_cb(m_claim_complete_write_cb); | ||||
|  | ||||
|     // port callbacks | ||||
|     SC_METHOD(global_int_port_cb); | ||||
|     for (uint8_t i = 0; i < 255; i++) { | ||||
|         sensitive << global_interrupts_i[i].pos(); | ||||
|     } | ||||
|     dont_initialize(); | ||||
|  | ||||
|     // register event callbacks | ||||
|     SC_METHOD(clock_cb); | ||||
|     sensitive << clk_i; | ||||
|     SC_METHOD(reset_cb); | ||||
|     sensitive << rst_i; | ||||
| } | ||||
|  | ||||
| plic::~plic() = default; | ||||
|  | ||||
| void plic::init_callbacks() { | ||||
|     m_claim_complete_write_cb = [=](scc::sc_register<uint32_t> reg, uint32_t v) -> bool { | ||||
|         reg.put(v); | ||||
|         reset_pending_int(v); | ||||
|         // std::cout << "Value of register: 0x" << std::hex << reg << std::endl; | ||||
|         // todo: reset related interrupt and find next high-prio interrupt | ||||
|         return true; | ||||
|     }; | ||||
| } | ||||
|  | ||||
| void plic::clock_cb() { this->clk = clk_i.read(); } | ||||
|  | ||||
| void plic::reset_cb() { | ||||
|     if (rst_i.read()) | ||||
|         regs->reset_start(); | ||||
|     else | ||||
|         regs->reset_stop(); | ||||
| } | ||||
|  | ||||
| // Functional handling of interrupts: | ||||
| // - global_int_port_cb() | ||||
| //   - set pending register bits | ||||
| //   - called by: incoming global_int | ||||
| // - handle_pending_int() | ||||
| //   - update claim register content | ||||
| //   - generate core-interrupt pulse | ||||
| //   - called by: | ||||
| //     - incoming global_int | ||||
| //     - complete-register write access | ||||
| // - reset_pending_int(int-id) | ||||
| //   - reset pending bit | ||||
| //   - call next handle_pending_int() | ||||
| //   - called by: | ||||
| //     - complete-reg write register content | ||||
|  | ||||
| void plic::global_int_port_cb() { | ||||
|  | ||||
|     // set related pending bit if enable is set for incoming global_interrupt | ||||
|  | ||||
|     // todo: extend up to 255 bits (limited to 32 right now) | ||||
|     for (uint32_t i = 1; i < 32; i++) { | ||||
|         uint32_t enable_bits = regs->r_enabled; | ||||
|         bool enable = enable_bits & (0x1 << i); // read enable bit | ||||
|  | ||||
|         if (enable && global_interrupts_i[i].read() == 1) { | ||||
|             regs->r_pending = regs->r_pending | (0x1 << i); | ||||
|             SCCDEBUG("plic") << "pending interrupt identified: " << i; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     handle_pending_int(); | ||||
| } | ||||
|  | ||||
| void plic::handle_pending_int() { | ||||
|     // identify high-prio pending interrupt and raise a core-interrupt | ||||
|     uint32_t claim_int = 0;  // claim interrupt | ||||
|     uint32_t claim_prio = 0; // related priority (highest prio interrupt wins the race) | ||||
|     bool raise_int = false; | ||||
|     uint32_t thold = regs->r_threshold.threshold; // threshold value | ||||
|  | ||||
|     // todo: extend up to 255 bits (limited to 32 right now) | ||||
|     for (uint32_t i = 1; i < 32; i++) { | ||||
|         uint32_t pending_bits = regs->r_pending; | ||||
|         bool pending = (pending_bits & (0x1 << i)) ? true : false; | ||||
|         uint32_t prio = regs->r_priority[i - 1].priority; // read priority value | ||||
|  | ||||
|         if (pending && thold < prio) { | ||||
|             regs->r_pending = regs->r_pending | (0x1 << i); | ||||
|             // below condition ensures implicitly that lowest id is selected in case of multiple identical | ||||
|             // priority-interrupts | ||||
|             if (prio > claim_prio) { | ||||
|                 claim_prio = prio; | ||||
|                 claim_int = i; | ||||
|                 raise_int = true; | ||||
|                 SCCDEBUG("plic") << "pending interrupt activated: " << i; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     if (raise_int) { | ||||
|         regs->r_claim_complete = claim_int; | ||||
|         core_interrupt_o.write(true); | ||||
|         // todo: evluate clock period | ||||
|     } else { | ||||
|         regs->r_claim_complete = 0; | ||||
|         SCCDEBUG("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. | ||||
|     SCCDEBUG("plic") << "reset pending interrupt: " << irq; | ||||
|     // reset related pending bit | ||||
|     regs->r_pending &= ~(0x1 << irq); | ||||
|     core_interrupt_o.write(false); | ||||
|  | ||||
|     // evaluate next pending interrupt | ||||
|     handle_pending_int(); | ||||
| } | ||||
|  | ||||
| } /* namespace sysc */ | ||||
| @@ -1,57 +0,0 @@ | ||||
| /******************************************************************************* | ||||
|  * 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. | ||||
|  ******************************************************************************/ | ||||
|  | ||||
| #ifndef _PLIC_H_ | ||||
| #define _PLIC_H_ | ||||
|  | ||||
| #include <scc/register.h> | ||||
| #include <scc/tlm_target.h> | ||||
|  | ||||
| namespace sysc { | ||||
|  | ||||
| class plic_regs; | ||||
|  | ||||
| class plic : public sc_core::sc_module, public scc::tlm_target<> { | ||||
| public: | ||||
|     SC_HAS_PROCESS(plic); | ||||
|     sc_core::sc_in<sc_core::sc_time> clk_i; | ||||
|     sc_core::sc_in<bool> rst_i; | ||||
|     sc_core::sc_vector<sc_core::sc_in<bool>> global_interrupts_i; | ||||
|     sc_core::sc_out<bool> core_interrupt_o; | ||||
|     sc_core::sc_event raise_int_ev; | ||||
|     sc_core::sc_event clear_int_ev; | ||||
|     plic(sc_core::sc_module_name nm); | ||||
|     virtual ~plic(); | ||||
|  | ||||
| protected: | ||||
|     void clock_cb(); | ||||
|     void reset_cb(); | ||||
|     void init_callbacks(); | ||||
|  | ||||
|     void global_int_port_cb(); | ||||
|     void handle_pending_int(); | ||||
|     void reset_pending_int(uint32_t irq); | ||||
|  | ||||
|     void raise_core_interrupt(); | ||||
|     void clear_core_interrupt(); | ||||
|     sc_core::sc_time clk; | ||||
|     std::unique_ptr<plic_regs> regs; | ||||
|     std::function<bool(scc::sc_register<uint32_t>, uint32_t)> m_claim_complete_write_cb; | ||||
| }; | ||||
|  | ||||
| } /* namespace sysc */ | ||||
|  | ||||
| #endif /* _PLIC_H_ */ | ||||
| @@ -1,92 +0,0 @@ | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| // 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. | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| /* | ||||
|  * sc_main.cpp | ||||
|  * | ||||
|  *  Created on: 17.09.2017 | ||||
|  *      Author: eyck@minres.com | ||||
|  */ | ||||
|  | ||||
| #include "simple_system.h" | ||||
| #include <scc/report.h> | ||||
| #include <scc/tracer.h> | ||||
| #include <boost/program_options.hpp> | ||||
|  | ||||
| using namespace sysc; | ||||
| using namespace scc; | ||||
| namespace po = boost::program_options; | ||||
|  | ||||
| namespace { | ||||
| const size_t ERROR_IN_COMMAND_LINE = 1; | ||||
| const size_t SUCCESS = 0; | ||||
| const size_t ERROR_UNHANDLED_EXCEPTION = 2; | ||||
| } // namespace | ||||
|  | ||||
| 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); | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     // CLI argument parsing | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     po::options_description desc("Options"); | ||||
|     // clang-format off | ||||
|     desc.add_options() | ||||
|     		("help,h",  "Print help message") | ||||
| 			("debug,d", "set debug level") | ||||
| 			("trace,t", "trace SystemC signals"); | ||||
|     // clang-format on | ||||
|     po::variables_map vm; | ||||
|     try { | ||||
|         po::store(po::parse_command_line(argc, argv, desc), vm); // can throw | ||||
|         // --help option | ||||
|         if (vm.count("help")) { | ||||
|             std::cout << "JIT-ISS simulator for AVR" << std::endl << desc << std::endl; | ||||
|             return SUCCESS; | ||||
|         } | ||||
|         po::notify(vm); // throws on error, so do after help in case | ||||
|         // there are any problems | ||||
|     } catch (po::error &e) { | ||||
|         std::cerr << "ERROR: " << e.what() << std::endl << std::endl; | ||||
|         std::cerr << desc << std::endl; | ||||
|         return ERROR_IN_COMMAND_LINE; | ||||
|     } | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     // configure logging | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     scc::init_logging(vm.count("debug")?scc::log::DEBUG:scc::log::INFO); | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     // set up tracing & transaction recording | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     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"); | ||||
|  | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     // run simulation | ||||
|     /////////////////////////////////////////////////////////////////////////// | ||||
|     sc_start(sc_core::sc_time(1, sc_core::SC_MS)); | ||||
|     // todo: provide end-of-simulation macros | ||||
|  | ||||
|     if (!sc_core::sc_end_of_simulation_invoked()) { | ||||
|         SCCERR() << "simulation timed out"; | ||||
|         sc_core::sc_stop(); | ||||
|     } | ||||
|     return SUCCESS; | ||||
| } | ||||
| @@ -1,87 +0,0 @@ | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| // 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. | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| /* | ||||
|  * simplesystem.cpp | ||||
|  * | ||||
|  *  Created on: 17.09.2017 | ||||
|  *      Author: eyck@minres.com | ||||
|  */ | ||||
|  | ||||
| #include "simple_system.h" | ||||
|  | ||||
| namespace sysc { | ||||
|  | ||||
| simple_system::simple_system(sc_core::sc_module_name nm) | ||||
| : sc_core::sc_module(nm) | ||||
| , NAMED(i_master) | ||||
| , NAMED(i_router, 4, 1) | ||||
| , NAMED(i_uart) | ||||
| , NAMED(i_spi) | ||||
| , NAMED(i_gpio) | ||||
| , NAMED(i_plic) | ||||
| , NAMED(s_clk) | ||||
| , NAMED(s_rst) | ||||
| , NAMED(s_global_interrupts, 256) | ||||
| , 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]); | ||||
|     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); | ||||
|     i_spi.clk_i(s_clk); | ||||
|     i_gpio.clk_i(s_clk); | ||||
|     i_plic.clk_i(s_clk); | ||||
|     s_clk.write(10_ns); | ||||
|  | ||||
|     i_uart.rst_i(s_rst); | ||||
|     i_spi.rst_i(s_rst); | ||||
|     i_gpio.rst_i(s_rst); | ||||
|     i_plic.rst_i(s_rst); | ||||
|     i_master.rst_i(s_rst); | ||||
|  | ||||
|     // interrupt connections | ||||
|     i_plic.core_interrupt_o(s_core_interrupt); | ||||
|     i_plic.global_interrupts_i.bind(s_global_interrupts); | ||||
|     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); | ||||
| } | ||||
|  | ||||
| void simple_system::gen_reset() { | ||||
|     s_rst = true; | ||||
|     wait(10_ns); | ||||
|     s_rst = false; | ||||
| } | ||||
|  | ||||
| } /* namespace sysc */ | ||||
| @@ -1,64 +0,0 @@ | ||||
| /******************************************************************************* | ||||
|  * 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. | ||||
|  ******************************************************************************/ | ||||
| /* | ||||
|  * simplesystem.h | ||||
|  * | ||||
|  *  Created on: 17.09.2017 | ||||
|  *      Author: eyck@minres.com | ||||
|  */ | ||||
|  | ||||
| #ifndef SIMPLESYSTEM_H_ | ||||
| #define SIMPLESYSTEM_H_ | ||||
|  | ||||
| #include "gpio.h" | ||||
| #include "plic.h" | ||||
| #include "spi.h" | ||||
| #include "uart.h" | ||||
|  | ||||
| #include "test_initiator.h" | ||||
| #include <array> | ||||
| #include <sysc/kernel/sc_module.h> | ||||
| #include <scc/router.h> | ||||
|  | ||||
| namespace sysc { | ||||
|  | ||||
| class simple_system : public sc_core::sc_module { | ||||
| public: | ||||
|     SC_HAS_PROCESS(simple_system); | ||||
|  | ||||
|     test_initiator i_master; | ||||
|     scc::router<> i_router; | ||||
|     uart i_uart; | ||||
|     spi i_spi; | ||||
|     gpio i_gpio; | ||||
|     plic i_plic; | ||||
|     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, sc_core::SC_MANY_WRITERS> s_core_interrupt; | ||||
|     sc_core::sc_vector<tlm::scc::tlm_signal<>> s_gpio; | ||||
|  | ||||
|     simple_system(sc_core::sc_module_name nm); | ||||
|  | ||||
| protected: | ||||
|     void gen_reset(); | ||||
|  | ||||
| #include "gen/e300_plat_t.h" | ||||
| }; | ||||
|  | ||||
| } /* namespace sysc */ | ||||
|  | ||||
| #endif /* SIMPLESYSTEM_H_ */ | ||||
| @@ -1,47 +0,0 @@ | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| // 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. | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| #include "spi.h" | ||||
| #include "gen/spi_regs.h" | ||||
| #include "scc/utilities.h" | ||||
|  | ||||
| namespace sysc { | ||||
|  | ||||
| spi::spi(sc_core::sc_module_name nm) | ||||
| : sc_core::sc_module(nm) | ||||
| , tlm_target<>(clk) | ||||
| , NAMED(clk_i) | ||||
| , NAMED(rst_i) | ||||
| , NAMEDD(regs, spi_regs) { | ||||
|     regs->registerResources(*this); | ||||
|     SC_METHOD(clock_cb); | ||||
|     sensitive << clk_i; | ||||
|     SC_METHOD(reset_cb); | ||||
|     sensitive << rst_i; | ||||
| } | ||||
|  | ||||
| spi::~spi() {} // NOLINT | ||||
|  | ||||
| void spi::clock_cb() { this->clk = clk_i.read(); } | ||||
|  | ||||
| void spi::reset_cb() { | ||||
|     if (rst_i.read()) | ||||
|         regs->reset_start(); | ||||
|     else | ||||
|         regs->reset_stop(); | ||||
| } | ||||
|  | ||||
| } /* namespace sysc */ | ||||
| @@ -1,43 +0,0 @@ | ||||
| /******************************************************************************* | ||||
|  * 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. | ||||
|  ******************************************************************************/ | ||||
|  | ||||
| #ifndef _SPI_H_ | ||||
| #define _SPI_H_ | ||||
|  | ||||
| #include <scc/tlm_target.h> | ||||
|  | ||||
| namespace sysc { | ||||
|  | ||||
| class spi_regs; | ||||
|  | ||||
| class spi : public sc_core::sc_module, public scc::tlm_target<> { | ||||
| public: | ||||
|     SC_HAS_PROCESS(spi); | ||||
|     sc_core::sc_in<sc_core::sc_time> clk_i; | ||||
|     sc_core::sc_in<bool> rst_i; | ||||
|     spi(sc_core::sc_module_name nm); | ||||
|     virtual ~spi(); | ||||
|  | ||||
| protected: | ||||
|     void clock_cb(); | ||||
|     void reset_cb(); | ||||
|     sc_core::sc_time clk; | ||||
|     std::unique_ptr<spi_regs> regs; | ||||
| }; | ||||
|  | ||||
| } /* namespace sysc */ | ||||
|  | ||||
| #endif /* _SPI_H_ */ | ||||
| @@ -1,272 +0,0 @@ | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| // 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. | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| /* | ||||
|  * test_initiator.cpp | ||||
|  * | ||||
|  *  Created on: 17.09.2017 | ||||
|  *      Author: eyck@minres.com | ||||
|  */ | ||||
|  | ||||
| #include "test_initiator.h" | ||||
| #include <array> | ||||
| #include <scc/report.h> | ||||
| #include <scc/utilities.h> | ||||
|  | ||||
| // todo: move into gen folder somewhere (adapt code-generator) | ||||
| #define PLIC_PRIO1_REG 0x0C000004 | ||||
| #define PLIC_PRIO2_REG 0x0C000008 | ||||
| #define PLIC_PRIO3_REG 0x0C00000C | ||||
| #define PLIC_PRIO4_REG 0x0C000010 | ||||
| #define PLIC_PENDING_REG 0x0C001000 | ||||
| #define PLIC_ENABLE_REG 0x0C002000 | ||||
| #define PLIC_PRIO_TRESHOLD_REG 0x0C200000 | ||||
| #define PLIC_CLAIM_COMPLETE_REG 0x0C200004 | ||||
|  | ||||
| namespace sysc { | ||||
| 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) | ||||
| , NAMED(core_interrupt_i) { | ||||
|     SC_THREAD(run); | ||||
|  | ||||
|     SC_METHOD(core_irq_handler); | ||||
|     sensitive << core_interrupt_i; | ||||
|     dont_initialize(); | ||||
| } | ||||
|  | ||||
| void test_initiator::run() { | ||||
|     // wait for reset | ||||
|     if (rst_i.read() == false) wait(rst_i.posedge_event()); | ||||
|     wait(rst_i.negedge_event()); | ||||
|     wait(10_ns); | ||||
|  | ||||
|     // apply test-sequences | ||||
|     test_unique_irq(); | ||||
|     test_frequent_irq(); | ||||
|     test_parallel_irq(); | ||||
|     test_irq_stress(); | ||||
|  | ||||
|     // todo: review irq sequences from FW point of view ... expected ??? | ||||
|     wait(100_ns); | ||||
|     sc_stop(); | ||||
| } | ||||
|  | ||||
| void test_initiator::test_unique_irq() { | ||||
|  | ||||
|     //// enable reg is not set | ||||
|     // -> irq to be ignored | ||||
|     // -> no core_interrupt | ||||
|     // -> no entry in pending reg | ||||
|  | ||||
|     // generate interrupt pulse (note: 1 is lowest usable register) | ||||
|     global_interrupts_o[2].write(true); | ||||
|     wait(10_ns); | ||||
|     global_interrupts_o[2].write(false); | ||||
|     wait(10_ns); | ||||
|  | ||||
|     reg_check(PLIC_PENDING_REG, 0x0); | ||||
|     wait(10_ns); | ||||
|     reg_check(PLIC_CLAIM_COMPLETE_REG, 0x0); | ||||
|     wait(10_ns); | ||||
|  | ||||
|     //// enable reg is set, then | ||||
|     // -> pending bit change expected | ||||
|     // -> core_interrupt expected | ||||
|  | ||||
|     read_bus(PLIC_PRIO1_REG); | ||||
|     wait(10_ns); | ||||
|  | ||||
|     // enable single interrupt | ||||
|     write_bus(PLIC_PRIO1_REG, 0x1); | ||||
|     wait(10_ns); | ||||
|  | ||||
|     write_bus(PLIC_ENABLE_REG, 0x2); | ||||
|     wait(10_ns); | ||||
|  | ||||
|     // generate interrupt pulse (note: 1 is lowest usable register) | ||||
|     global_interrupts_o[1].write(true); | ||||
|     wait(10_ns); | ||||
|     global_interrupts_o[1].write(false); | ||||
|     wait(10_ns); | ||||
|  | ||||
|     // read claim_complete register | ||||
|     reg_check(PLIC_PENDING_REG, 0x2); | ||||
|     wait(10_ns); | ||||
|     reg_check(PLIC_CLAIM_COMPLETE_REG, 0x1); | ||||
|     wait(10_ns); | ||||
|  | ||||
|     //// after writing to claim_complete reg (per fw) | ||||
|     // -> pending bit expected to be unset | ||||
|     // -> enable bit expected to be set ... test with / without enable being set | ||||
|     write_bus(PLIC_CLAIM_COMPLETE_REG, 0x1); | ||||
|     wait(10_ns); | ||||
|     reg_check(PLIC_PENDING_REG, 0x0); | ||||
|     wait(10_ns); | ||||
|     reg_check(PLIC_CLAIM_COMPLETE_REG, 0x0); | ||||
|     wait(10_ns); | ||||
|  | ||||
|     // todo: remove wait statements once the tlm_initiator is in place | ||||
|     // todo: evaluate error messages ... provide correct pass/fail verdict | ||||
|  | ||||
|     wait(100_ns); | ||||
| } | ||||
|  | ||||
| void test_initiator::test_frequent_irq() {} | ||||
|  | ||||
| void test_initiator::test_parallel_irq() { | ||||
|  | ||||
|     //// create three parallel global_int requests | ||||
|     // -> read and clear bits one after the other | ||||
|     // -> different priorities applied (reverse order) | ||||
|     // -> correct priority handing expected | ||||
|     // -> three core interrupts expected in total | ||||
|  | ||||
|     // reverse order priority configuration | ||||
|     write_bus(PLIC_PRIO1_REG, 0x3); | ||||
|     wait(10_ns); | ||||
|     write_bus(PLIC_PRIO2_REG, 0x2); | ||||
|     wait(10_ns); | ||||
|     write_bus(PLIC_PRIO3_REG, 0x1); | ||||
|     wait(10_ns); | ||||
|  | ||||
|     // enable all three interrupts | ||||
|     write_bus(PLIC_ENABLE_REG, 0xE); | ||||
|     wait(10_ns); | ||||
|  | ||||
|     // generate interrupt pulse (note: 1 is lowest usable register) | ||||
|     global_interrupts_o[1].write(true); | ||||
|     wait(10_ns); | ||||
|     global_interrupts_o[1].write(false); | ||||
|     wait(10_ns); | ||||
|     global_interrupts_o[2].write(true); | ||||
|     wait(10_ns); | ||||
|     global_interrupts_o[2].write(false); | ||||
|     wait(10_ns); | ||||
|     global_interrupts_o[3].write(true); | ||||
|     wait(10_ns); | ||||
|     global_interrupts_o[3].write(false); | ||||
|     wait(10_ns); | ||||
|  | ||||
|     // expect three pending registers | ||||
|     reg_check(PLIC_PENDING_REG, 0xE); | ||||
|     wait(10_ns); | ||||
|  | ||||
|     // expect lowest interrupt id to be highest int | ||||
|     reg_check(PLIC_CLAIM_COMPLETE_REG, 0x1); | ||||
|     wait(10_ns); | ||||
|  | ||||
|     //// after writing to claim_complete reg (per fw) | ||||
|     // -> next int to become highest irq | ||||
|     write_bus(PLIC_CLAIM_COMPLETE_REG, 0x1); | ||||
|     wait(10_ns); | ||||
|     reg_check(PLIC_PENDING_REG, 0xC); | ||||
|     wait(10_ns); | ||||
|     reg_check(PLIC_CLAIM_COMPLETE_REG, 0x2); | ||||
|     wait(10_ns); | ||||
|  | ||||
|     //// after writing to claim_complete reg again (per fw) | ||||
|     // -> next int to become highest irq | ||||
|     write_bus(PLIC_CLAIM_COMPLETE_REG, 0x2); | ||||
|     wait(10_ns); | ||||
|     reg_check(PLIC_PENDING_REG, 0x8); | ||||
|     wait(10_ns); | ||||
|     reg_check(PLIC_CLAIM_COMPLETE_REG, 0x3); | ||||
|     wait(10_ns); | ||||
|  | ||||
|     //// after last writing to claim_complete reg again (per fw) | ||||
|     // -> no further pending irq expected | ||||
|     write_bus(PLIC_CLAIM_COMPLETE_REG, 0x3); | ||||
|     wait(10_ns); | ||||
|     reg_check(PLIC_PENDING_REG, 0x0); | ||||
|     wait(10_ns); | ||||
|     reg_check(PLIC_CLAIM_COMPLETE_REG, 0x0); | ||||
|     wait(10_ns); | ||||
|  | ||||
|     // todo: advance upon register-write access ... remove above 10_ns waits | ||||
|     // todo: evaluate error messages ... provide correct pass/fail verdict | ||||
|  | ||||
|     wait(100_ns); | ||||
| } | ||||
|  | ||||
| void test_initiator::test_irq_stress() {} | ||||
|  | ||||
| void test_initiator::write_bus(std::uint32_t adr, std::uint32_t dat) { | ||||
|     tlm::tlm_generic_payload gp; | ||||
|     std::array<uint8_t, 4> data; | ||||
|     data[3] = 0xff & dat >> 24; | ||||
|     data[2] = 0xff & dat >> 16; | ||||
|     data[1] = 0xff & dat >> 8; | ||||
|     data[0] = 0xff & dat; | ||||
|  | ||||
|     SCCDEBUG("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_time delay; | ||||
|     intor->b_transport(gp, delay); | ||||
|  | ||||
|     if (gp.get_response_status() != tlm::TLM_OK_RESPONSE) { | ||||
|         throw std::exception(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| std::uint32_t test_initiator::read_bus(std::uint32_t adr) { | ||||
|  | ||||
|     tlm::tlm_generic_payload gp; | ||||
|     std::array<uint8_t, 4> data; | ||||
|  | ||||
|     gp.set_command(tlm::TLM_READ_COMMAND); | ||||
|     gp.set_address(adr); | ||||
|     gp.set_data_ptr(data.data()); | ||||
|     gp.set_data_length(data.size()); | ||||
|     gp.set_streaming_width(4); | ||||
|     sc_time delay; | ||||
|     intor->b_transport(gp, delay); | ||||
|  | ||||
|     if (gp.get_response_status() != tlm::TLM_OK_RESPONSE) { | ||||
|         // todo: improve output in case of exception, define own exception class to carry transaction-infos | ||||
|         // ... i.e. out-of-range report with info about legal mem boundaries | ||||
|         throw std::exception(); | ||||
|     } | ||||
|  | ||||
|     // todo: use reinterpret_cast instead | ||||
|     std::uint32_t rdat = data[3] << 24 | data[2] << 16 | data[1] << 8 | data[0]; | ||||
|  | ||||
|     SCCDEBUG("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) { | ||||
|         SCCERR("test_initiator") << "register check failed for address 0x" << std::hex << adr << ": " << dat << " !=  " << exp; | ||||
|     } else { | ||||
|         SCCDEBUG("test_initiator") << "register check passed for address 0x" << std::hex << adr << ": " << dat; | ||||
|     } | ||||
| } | ||||
|  | ||||
| void test_initiator::core_irq_handler() { | ||||
|     SCCDEBUG("test_initiator") << "core_interrupt_i edge detected -> " << core_interrupt_i.read(); | ||||
| } | ||||
|  | ||||
| } /* namespace sysc */ | ||||
| @@ -1,55 +0,0 @@ | ||||
| /******************************************************************************* | ||||
|  * 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. | ||||
|  ******************************************************************************/ | ||||
| /* | ||||
|  * test_initiator.h | ||||
|  * | ||||
|  *  Created on: 17.09.2017 | ||||
|  *      Author: eyck@minres.com | ||||
|  */ | ||||
|  | ||||
| #ifndef _TEST_INITIATOR_H_ | ||||
| #define _TEST_INITIATOR_H_ | ||||
|  | ||||
| #include <scc/utilities.h> | ||||
| #include <tlm_utils/simple_initiator_socket.h> | ||||
|  | ||||
| namespace sysc { | ||||
|  | ||||
| class test_initiator : public sc_core::sc_module { | ||||
| public: | ||||
|     SC_HAS_PROCESS(test_initiator); | ||||
|     tlm_utils::simple_initiator_socket<test_initiator, 32> intor; | ||||
|     sc_core::sc_vector<sc_core::sc_out<bool>> global_interrupts_o; | ||||
|     sc_core::sc_in<bool> core_interrupt_i; | ||||
|     sc_core::sc_in<bool> rst_i; | ||||
|     test_initiator(sc_core::sc_module_name nm); | ||||
|  | ||||
| protected: | ||||
|     void run(); | ||||
|     void test_unique_irq(); | ||||
|     void test_frequent_irq(); | ||||
|     void test_parallel_irq(); | ||||
|     void test_irq_stress(); | ||||
|     void write_bus(std::uint32_t adr, std::uint32_t dat); | ||||
|     std::uint32_t read_bus(std::uint32_t adr); | ||||
|     void reg_check(std::uint32_t adr, std::uint32_t exp); | ||||
|  | ||||
|     void core_irq_handler(); | ||||
| }; | ||||
|  | ||||
| } /* namespace sysc */ | ||||
|  | ||||
| #endif /* _TEST_INITIATOR_H_ */ | ||||
| @@ -1,47 +0,0 @@ | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
| // 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. | ||||
| //////////////////////////////////////////////////////////////////////////////// | ||||
|  | ||||
| #include "uart.h" | ||||
| #include "gen/uart_regs.h" | ||||
| #include "scc/utilities.h" | ||||
|  | ||||
| namespace sysc { | ||||
|  | ||||
| uart::uart(sc_core::sc_module_name nm) | ||||
| : sc_core::sc_module(nm) | ||||
| , tlm_target<>(clk) | ||||
| , NAMED(clk_i) | ||||
| , NAMED(rst_i) | ||||
| , NAMEDD(regs, uart_regs) { | ||||
|     regs->registerResources(*this); | ||||
|     SC_METHOD(clock_cb); | ||||
|     sensitive << clk_i; | ||||
|     SC_METHOD(reset_cb); | ||||
|     sensitive << rst_i; | ||||
| } | ||||
|  | ||||
| uart::~uart() {} // NOLINT | ||||
|  | ||||
| void uart::clock_cb() { this->clk = clk_i.read(); } | ||||
|  | ||||
| void uart::reset_cb() { | ||||
|     if (rst_i.read()) | ||||
|         regs->reset_start(); | ||||
|     else | ||||
|         regs->reset_stop(); | ||||
| } | ||||
|  | ||||
| } /* namespace sysc */ | ||||
| @@ -1,43 +0,0 @@ | ||||
| /******************************************************************************* | ||||
|  * 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. | ||||
|  ******************************************************************************/ | ||||
|  | ||||
| #ifndef _UART_H_ | ||||
| #define _UART_H_ | ||||
|  | ||||
| #include <scc/tlm_target.h> | ||||
|  | ||||
| namespace sysc { | ||||
|  | ||||
| class uart_regs; | ||||
|  | ||||
| class uart : public sc_core::sc_module, public scc::tlm_target<> { | ||||
| public: | ||||
|     SC_HAS_PROCESS(uart); | ||||
|     sc_core::sc_in<sc_core::sc_time> clk_i; | ||||
|     sc_core::sc_in<bool> rst_i; | ||||
|     uart(sc_core::sc_module_name nm); | ||||
|     virtual ~uart(); | ||||
|  | ||||
| protected: | ||||
|     void clock_cb(); | ||||
|     void reset_cb(); | ||||
|     sc_core::sc_time clk; | ||||
|     std::unique_ptr<uart_regs> regs; | ||||
| }; | ||||
|  | ||||
| } /* namespace sysc */ | ||||
|  | ||||
| #endif /* _UART_H_ */ | ||||
| @@ -1,7 +0,0 @@ | ||||
| cmake_minimum_required(VERSION 3.12) | ||||
| add_executable (transaction_recording | ||||
| 	scv_tr_recording_example.cpp | ||||
| ) | ||||
| target_link_libraries (transaction_recording LINK_PUBLIC scc) | ||||
|  | ||||
| add_test(NAME tx_rec_test COMMAND transaction_recording) | ||||
| @@ -1,406 +0,0 @@ | ||||
| //  -*- C++ -*- <this line is for emacs to recognize it as C++ code> | ||||
| /***************************************************************************** | ||||
|  | ||||
|  The following code is derived, directly or indirectly, from the SystemC | ||||
|  source code Copyright (c) 1996-2014 by all Contributors. | ||||
|  All Rights reserved. | ||||
|  | ||||
|  The contents of this file are subject to the restrictions and limitations | ||||
|  set forth in the SystemC Open Source License (the "License"); | ||||
|  You may not use this file except in compliance with such restrictions and | ||||
|  limitations. You may obtain instructions on how to receive a copy of the | ||||
|  License at http://www.accellera.org/. Software distributed by Contributors | ||||
|  under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF | ||||
|  ANY KIND, either express or implied. See the License for the specific | ||||
|  language governing rights and limitations under the License. | ||||
|  | ||||
|  *****************************************************************************/ | ||||
| #include "scv.h" | ||||
| #include "scc/scv_tr_db.h" | ||||
| #include "scc/report.h" | ||||
| #include "scc/value_registry.h" | ||||
| #include <chrono> | ||||
|  | ||||
| // text         11308µs/11602µs | ||||
| // compressed   10365µs/ 9860µs | ||||
| // binary       13233µs/10698µs | ||||
| // SQLite       30363µs/30018µs | ||||
| // LeveDB       23898µs/22367µs | ||||
|  | ||||
| // hack to fake a true fifo_mutex | ||||
| #define fifo_mutex sc_mutex | ||||
|  | ||||
| const unsigned ram_size = 256; | ||||
|  | ||||
| class rw_task_if : virtual public sc_interface { | ||||
| public: | ||||
|     using addr_t = sc_uint<8>; | ||||
|     using data_t = sc_uint<8>; | ||||
|     struct write_t { | ||||
|         addr_t addr; | ||||
|         data_t data; | ||||
|     }; | ||||
|  | ||||
|     virtual data_t read(const addr_t *) = 0; | ||||
|     virtual void write(const write_t *) = 0; | ||||
| }; | ||||
|  | ||||
| SCV_EXTENSIONS(rw_task_if::write_t) { | ||||
| public: | ||||
|     scv_extensions<rw_task_if::addr_t> addr; | ||||
|     scv_extensions<rw_task_if::data_t> data; | ||||
|     SCV_EXTENSIONS_CTOR(rw_task_if::write_t) { | ||||
|         SCV_FIELD(addr); | ||||
|         SCV_FIELD(data); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| class pipelined_bus_ports : public sc_module { | ||||
| public: | ||||
|     sc_in<bool> clk; | ||||
|     sc_inout<bool> rw; | ||||
|     sc_inout<bool> addr_req; | ||||
|     sc_inout<bool> addr_ack; | ||||
|     sc_inout<sc_uint<8>> bus_addr; | ||||
|     sc_inout<bool> data_rdy; | ||||
|     sc_inout<sc_uint<8>> bus_data; | ||||
|  | ||||
|     SC_CTOR(pipelined_bus_ports) | ||||
|     : clk("clk") | ||||
|     , rw("rw") | ||||
|     , addr_req("addr_req") | ||||
|     , addr_ack("addr_ack") | ||||
|     , bus_addr("bus_addr") | ||||
|     , data_rdy("data_rdy") | ||||
|     , bus_data("bus_data") {} | ||||
|     void trace(sc_trace_file *tf) const override; | ||||
| }; | ||||
|  | ||||
| void pipelined_bus_ports::trace(sc_trace_file *tf) const { | ||||
|     sc_trace(tf, clk, clk.name()); | ||||
|     sc_trace(tf, rw, rw.name()); | ||||
|     sc_trace(tf, addr_req, addr_req.name()); | ||||
|     sc_trace(tf, addr_ack, addr_ack.name()); | ||||
|     sc_trace(tf, bus_addr, bus_addr.name()); | ||||
|     sc_trace(tf, data_rdy, data_rdy.name()); | ||||
|     sc_trace(tf, bus_data, bus_data.name()); | ||||
| } | ||||
|  | ||||
| class rw_pipelined_transactor : public rw_task_if, public pipelined_bus_ports { | ||||
|  | ||||
|     fifo_mutex addr_phase; | ||||
|     fifo_mutex data_phase; | ||||
|  | ||||
|     scv_tr_stream pipelined_stream; | ||||
|     scv_tr_stream addr_stream; | ||||
|     scv_tr_stream data_stream; | ||||
|     scv_tr_generator<sc_uint<8>, sc_uint<8>> read_gen; | ||||
|     scv_tr_generator<sc_uint<8>, sc_uint<8>> write_gen; | ||||
|     scv_tr_generator<sc_uint<8>> addr_gen; | ||||
|     scv_tr_generator<_scv_tr_generator_default_data, sc_uint<8>> rdata_gen; | ||||
|     scv_tr_generator<sc_uint<8>> wdata_gen; | ||||
|  | ||||
| public: | ||||
|     rw_pipelined_transactor(sc_module_name nm) | ||||
|     : pipelined_bus_ports(nm) | ||||
|     , addr_phase("addr_phase") | ||||
|     , data_phase("data_phase") | ||||
|     , pipelined_stream((std::string(name()) + ".pipelined_stream").c_str(), "transactor") | ||||
|     , addr_stream((std::string(name()) + ".addr_stream").c_str(), "transactor") | ||||
|     , data_stream((std::string(name()) + ".data_stream").c_str(), "transactor") | ||||
|     , read_gen("read", pipelined_stream, "addr", "data") | ||||
|     , write_gen("write", pipelined_stream, "addr", "data") | ||||
|     , addr_gen("addr", addr_stream, "addr") | ||||
|     , rdata_gen("rdata", data_stream, nullptr, "data") | ||||
|     , wdata_gen("wdata", data_stream, "data") {} | ||||
|     data_t read(const addr_t *p_addr) override; | ||||
|     void write(const write_t *req) override; | ||||
| }; | ||||
|  | ||||
| rw_task_if::data_t rw_pipelined_transactor::read(const addr_t *addr) { | ||||
|     addr_phase.lock(); | ||||
|     scv_tr_handle h = read_gen.begin_transaction(*addr); | ||||
|     h.record_attribute("data_size", sizeof(data_t)); | ||||
|     scv_tr_handle h1 = addr_gen.begin_transaction(*addr, "addr_phase", h); | ||||
|     wait(clk->posedge_event()); | ||||
|     bus_addr = *addr; | ||||
|     rw = false; | ||||
|     addr_req = true; | ||||
|     wait(addr_ack->posedge_event()); | ||||
|     wait(clk->negedge_event()); | ||||
|     addr_req = false; | ||||
|     wait(addr_ack->negedge_event()); | ||||
|     addr_gen.end_transaction(h1); | ||||
|     addr_phase.unlock(); | ||||
|  | ||||
|     data_phase.lock(); | ||||
|     scv_tr_handle h2 = rdata_gen.begin_transaction("data_phase", h); | ||||
|     wait(data_rdy->posedge_event()); | ||||
|     data_t data = bus_data.read(); | ||||
|     wait(data_rdy->negedge_event()); | ||||
|     rdata_gen.end_transaction(h2, data); | ||||
|     read_gen.end_transaction(h, data); | ||||
|     data_phase.unlock(); | ||||
|  | ||||
|     return data; | ||||
| } | ||||
|  | ||||
| void rw_pipelined_transactor::write(const write_t *req) { | ||||
|     addr_phase.lock(); | ||||
|     scv_tr_handle h = write_gen.begin_transaction(req->addr); | ||||
|     h.record_attribute("data_size", sizeof(data_t)); | ||||
|     scv_tr_handle h1 = addr_gen.begin_transaction(req->addr, "addr_phase", h); | ||||
|     wait(clk->posedge_event()); | ||||
|     bus_addr = req->addr; | ||||
|     rw = true; | ||||
|     addr_req = true; | ||||
|     wait(addr_ack->posedge_event()); | ||||
|     wait(clk->negedge_event()); | ||||
|     addr_req = false; | ||||
|     wait(addr_ack->negedge_event()); | ||||
|     addr_gen.end_transaction(h1); | ||||
|     addr_phase.unlock(); | ||||
|  | ||||
|     data_phase.lock(); | ||||
|     scv_tr_handle h2 = wdata_gen.begin_transaction(req->data, "data_phase", h); | ||||
|     bus_data = req->data; | ||||
|     wait(data_rdy->posedge_event()); | ||||
|     wait(data_rdy->negedge_event()); | ||||
|     wdata_gen.end_transaction(h2); | ||||
|     write_gen.end_transaction(h, req->data); | ||||
|     data_phase.unlock(); | ||||
| } | ||||
|  | ||||
| class test : public sc_module { | ||||
| public: | ||||
|     sc_port<rw_task_if> transactor; | ||||
|     SC_HAS_PROCESS(test); | ||||
|     test(::sc_core::sc_module_name) { | ||||
|         SC_THREAD(main1); | ||||
|         SC_THREAD(main2); | ||||
|     } | ||||
|     void main1(); | ||||
|     void main2(); | ||||
| }; | ||||
|  | ||||
| class write_constraint : virtual public scv_constraint_base { | ||||
| public: | ||||
|     scv_smart_ptr<rw_task_if::write_t> write; | ||||
|     SCV_CONSTRAINT_CTOR(write_constraint) { // NOLINT | ||||
|         SCV_CONSTRAINT(write->addr() <= ram_size); // NOLINT | ||||
|         SCV_CONSTRAINT(write->addr() != write->data()); // NOLINT | ||||
|     } | ||||
| }; | ||||
|  | ||||
| inline void process(scv_smart_ptr<int> data) {} | ||||
|  | ||||
| inline void test::main1() { | ||||
|     // simple sequential tests | ||||
|     for (int i = 0; i < 3; i++) { | ||||
|         rw_task_if::addr_t addr = i; | ||||
|         rw_task_if::data_t data = transactor->read(&addr); | ||||
|         SCCINFO(sc_get_current_object()->name())  << "received data : " << data; | ||||
|     } | ||||
|  | ||||
|     scv_smart_ptr<rw_task_if::addr_t> addr; | ||||
|     for (int i = 0; i < 3; i++) { | ||||
|  | ||||
|         addr->next(); | ||||
|         rw_task_if::data_t data = transactor->read(addr->get_instance()); | ||||
|         SCCINFO(sc_get_current_object()->name()) << "data for address " << *addr << " is " << data; | ||||
|     } | ||||
|  | ||||
|     scv_smart_ptr<rw_task_if::write_t> write; | ||||
|     for (int i = 0; i < 3; i++) { | ||||
|         write->next(); | ||||
|         transactor->write(write->get_instance()); | ||||
|         SCCINFO(sc_get_current_object()->name()) << "send data : " << write->data; | ||||
|     } | ||||
|  | ||||
|     scv_smart_ptr<int> data; | ||||
|     scv_bag<int> distribution; | ||||
|     distribution.push(1, 40); | ||||
|     distribution.push(2, 60); | ||||
|     data->set_mode(distribution); | ||||
|     for (int i = 0; i < 3; i++) { | ||||
|         data->next(); | ||||
|         process(data); | ||||
|     } | ||||
| } | ||||
|  | ||||
| inline void test::main2() { | ||||
|     // simple sequential tests | ||||
|     for (int i = 0; i < 3; i++) { | ||||
|         rw_task_if::addr_t addr = i; | ||||
|         rw_task_if::data_t data = transactor->read(&addr); | ||||
|         SCCINFO(sc_get_current_object()->name())  << "received data : " << data; | ||||
|     } | ||||
|  | ||||
|     scv_smart_ptr<rw_task_if::addr_t> addr; | ||||
|     for (int i = 0; i < 3; i++) { | ||||
|  | ||||
|         addr->next(); | ||||
|         rw_task_if::data_t data = transactor->read(addr->get_instance()); | ||||
|         SCCINFO(sc_get_current_object()->name()) << "data for address " << *addr << " is " << data; | ||||
|     } | ||||
|  | ||||
|     scv_smart_ptr<rw_task_if::write_t> write; | ||||
|     for (int i = 0; i < 3; i++) { | ||||
|         write->next(); | ||||
|         transactor->write(write->get_instance()); | ||||
|         SCCINFO(sc_get_current_object()->name()) << "send data : " << write->data; | ||||
|     } | ||||
|  | ||||
|     scv_smart_ptr<int> data; | ||||
|     scv_bag<int> distribution; | ||||
|     distribution.push(1, 140); | ||||
|     distribution.push(2, 160); | ||||
|     data->set_mode(distribution); | ||||
|     for (int i = 0; i < 3; i++) { | ||||
|         data->next(); | ||||
|         process(data); | ||||
|     } | ||||
| } | ||||
| class design : public pipelined_bus_ports { | ||||
|     std::list<sc_uint<8>> outstandingAddresses; | ||||
|     std::list<bool> outstandingType; | ||||
|     sc_uint<8> memory[ram_size]; | ||||
|  | ||||
| public: | ||||
|     SC_HAS_PROCESS(design); | ||||
|     design(sc_module_name nm) | ||||
|     : pipelined_bus_ports(nm) { | ||||
|         for (unsigned i = 0; i < ram_size; ++i) { | ||||
|             memory[i] = i; | ||||
|         } | ||||
|         SC_THREAD(addr_phase); | ||||
|         SC_THREAD(data_phase); | ||||
|     } | ||||
|     void addr_phase(); | ||||
|     void data_phase(); | ||||
| }; | ||||
|  | ||||
| inline void design::addr_phase() { | ||||
|     while (true) { | ||||
|         while (addr_req.read() != 1) { | ||||
|             wait(addr_req->value_changed_event()); | ||||
|         } | ||||
|         sc_uint<8> _addr = bus_addr.read(); | ||||
|         bool _rw = rw.read(); | ||||
|  | ||||
|         int cycle = rand() % 10 + 1; | ||||
|         while (cycle-- > 0) { | ||||
|             wait(clk->posedge_event()); | ||||
|         } | ||||
|  | ||||
|         addr_ack = true; | ||||
|         wait(clk->posedge_event()); | ||||
|         addr_ack = false; | ||||
|  | ||||
|         outstandingAddresses.push_back(_addr); | ||||
|         outstandingType.push_back(_rw); | ||||
|         SCCINFO(sc_get_current_object()->name())  << "received request for memory address " << _addr; | ||||
|     } | ||||
| } | ||||
|  | ||||
| inline void design::data_phase() { | ||||
|     while (true) { | ||||
|         while (outstandingAddresses.empty()) { | ||||
|             wait(clk->posedge_event()); | ||||
|         } | ||||
|         int cycle = rand() % 10 + 1; | ||||
|         while (cycle-- > 0) { | ||||
|             wait(clk->posedge_event()); | ||||
|         } | ||||
|         if (outstandingType.front() == false) { | ||||
|             SCCINFO(sc_get_current_object()->name()) << "reading memory address " << outstandingAddresses.front() << " with value " | ||||
|                  << memory[outstandingAddresses.front().to_ulong()]; | ||||
|             bus_data = memory[outstandingAddresses.front().to_ulong()]; | ||||
|             data_rdy = true; | ||||
|             wait(clk->posedge_event()); | ||||
|             data_rdy = false; | ||||
|  | ||||
|         } else { | ||||
|             SCCINFO(sc_get_current_object()->name()) << "writing memory address " << outstandingAddresses.front() << " with value " << bus_data; | ||||
|             memory[outstandingAddresses.front().to_ulong()] = bus_data; | ||||
|             data_rdy = true; | ||||
|             wait(clk->posedge_event()); | ||||
|             data_rdy = false; | ||||
|         } | ||||
|         outstandingAddresses.pop_front(); | ||||
|         outstandingType.pop_front(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| inline const char* init_db(char type){ | ||||
|     switch(type){ | ||||
|     case '2': | ||||
|         scv_tr_compressed_init(); | ||||
|         return "my_db.txlog"; | ||||
|         break; | ||||
|     case '3': | ||||
|         scv_tr_sqlite_init(); | ||||
|         return "my_db.txdb"; | ||||
|         break; | ||||
|     default: | ||||
|         scv_tr_text_init(); | ||||
|         return "my_db.txlog"; | ||||
|         break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| int sc_main(int argc, char *argv[]) { | ||||
|     auto start = std::chrono::system_clock::now(); | ||||
|     scv_startup(); | ||||
|     scc::init_logging(scc::LogConfig().logLevel(scc::log::DEBUG)); | ||||
|     const char *fileName = argc==2? init_db(argv[1][0]): "my_db.txlog"; | ||||
|     if(argc<2) scv_tr_text_init(); | ||||
|     scv_tr_db db(fileName); | ||||
|     scv_tr_db::set_default_db(&db); | ||||
|     sc_trace_file *tf = sc_create_vcd_trace_file("my_db"); | ||||
|     // create signals | ||||
|     sc_clock clk("clk", 20.0, SC_NS, 0.5, 0.0, SC_NS, true); | ||||
|     sc_signal<bool> rw; | ||||
|     sc_signal<bool> addr_req; | ||||
|     sc_signal<bool> addr_ack; | ||||
|     sc_signal<sc_uint<8>> bus_addr; | ||||
|     sc_signal<bool> data_rdy; | ||||
|     sc_signal<sc_uint<8>> bus_data; | ||||
|  | ||||
|     scc::value_registry registry; | ||||
|     // create modules/channels | ||||
|     test t("t"); | ||||
|     rw_pipelined_transactor tr("tr"); | ||||
|     design duv("duv"); | ||||
|  | ||||
|     // connect them up | ||||
|     t.transactor(tr); | ||||
|  | ||||
|     tr.clk(clk); | ||||
|     tr.rw(rw); | ||||
|     tr.addr_req(addr_req); | ||||
|     tr.addr_ack(addr_ack); | ||||
|     tr.bus_addr(bus_addr); | ||||
|     tr.data_rdy(data_rdy); | ||||
|     tr.bus_data(bus_data); | ||||
|     tr.trace(tf); | ||||
|  | ||||
|     duv.clk(clk); | ||||
|     duv.rw(rw); | ||||
|     duv.addr_req(addr_req); | ||||
|     duv.addr_ack(addr_ack); | ||||
|     duv.bus_addr(bus_addr); | ||||
|     duv.data_rdy(data_rdy); | ||||
|     duv.bus_data(bus_data); | ||||
|     duv.trace(tf); | ||||
|  | ||||
|     // Accellera SystemC >=2.2 got picky about multiple drivers. | ||||
|     // Disable check for bus simulation. | ||||
|     sc_report_handler::set_actions(SC_ID_MORE_THAN_ONE_SIGNAL_DRIVER_, SC_DO_NOTHING); | ||||
|     // run the simulation | ||||
|     sc_start(10.0, SC_US); | ||||
|     sc_close_vcd_trace_file(tf); | ||||
|     auto int_us = std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now()-start); | ||||
|     SCCINFO() << "simulation duration "<<int_us.count()<<"µs"; | ||||
|     return 0; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user