Jump to content

Leaderboard

Popular Content

Showing content with the highest reputation since 07/01/2021 in all areas

  1. The simplest solution would be to pass a pointer (or reference) to OS_Task or the TCB with task_create() and task_end(). A forward declaration alogn with the OS_API class should be sufficient. I don't know your requirements but it seems to me that your use of sc_module is sub-optimal for the purpose of modeling OS tasks. The reason is simple: you cannot create or delete sc_module after the elaboration phase. And OS tasks tend to be dynamic... So sc_object and sc_spawn might be a better solution. I assume that task_create() and task_end() always surround the behavior of a task. So why not move them into the OS_Task itself? If you pass then the TCB as pointer or by reference you could encapsulate the entire stuff of task handling in the OS_task class...
    1 point
  2. 4,770 downloads

    This file, when sourced via your .vimrc file, highlights the HDL (Verilog, SystemVerilog) and Methodology layer (UVM) keywords in the vim editor.
    1 point
  3. Actually, it adds a lot of value. std::array can be passed by reference in a function call and the function can then determine the proper size of the array. This is much better than passing pointers, the C standard. You can also copy an array, which should be synthesizable, which reduces coding and greatly improves readability. It should be possible to implement some #include <algorithm>s on std::array too. Also, you can have bounds checking for additional safety; although, that aspect is probably not synthesizable. Additionally, constexpr should be quite helpful for the synthesis aspect.
    1 point
  4. tymonx

    Unit testing with gtest

    You must create all necessary SystemC signals, SystemC modules and make connection between them before you run any test in gtest. This require to create own gtest_main.cc implementation. Naturally in SystemC you must put everything in sc_main() function. For this, I would use registry design pattern. First create registry class (registry + factory + singleton). This class will be responsible for storing registered constructors using dynamic allocation with new and smart pointer in lambda expression (see factory::add class). Create all objects using factory::create() method before running all tests. Then you can get object using factory::get() method in you test execution. factory.hpp #ifndef FACTORY_HPP #define FACTORY_HPP #include <map> #include <string> #include <memory> #include <functional> class factory { public: static factory& get_instance(); template<typename T, typename ...Args> class add { public: add(Args&&... args); add(const std::string& name, Args&&... args); }; template<typename T> static T* get(const std::string& name = ""); void create(); void destroy(); private: using destructor = std::function<void(void*)>; using object = std::unique_ptr<void, destructor>; using constructor = std::function<object(void)>; factory(); factory(const factory& other) = delete; factory& operator=(const factory& other) = delete; void add_object(const std::string& name, constructor create); void* get_object(const std::string& name); std::map<std::string, constructor> m_constructors; std::map<std::string, object> m_objects; }; template<typename T, typename ...Args> factory::add<T, Args...>::add(Args&&... args) { add("", args...); } template<typename T, typename ...Args> factory::add<T, Args...>::add(const std::string& name, Args&&... args) { factory::get_instance().add_object(name, [args...] () -> object { return object{ new T(std::forward<Args>(args)...), [] (void* obj) { delete static_cast<T*>(obj); } }; } ); } template<typename T> auto factory::get(const std::string& name) -> T* { return static_cast<T*>(factory::get_instance().get_object(name)); } #endif /* FACTORY_HPP */ factory.cpp #include "factory.hpp" #include <stdexcept> auto factory::get_instance() -> factory& { static factory instance{}; return instance; } factory::factory() : m_constructors{}, m_objects{} { } void factory::create() { for (const auto& item : m_constructors) { m_objects[item.first] = item.second(); } } void factory::destroy() { m_objects.clear(); } void factory::add_object(const std::string& name, constructor create) { auto it = m_constructors.find(name); if (it == m_constructors.cend()) { m_constructors[name] = create; } else { throw std::runtime_error("factory::add(): " + name + " object already exist in factory"); } } auto factory::get_object(const std::string& name) -> void* { auto it = m_objects.find(name); if (it == m_objects.cend()) { throw std::runtime_error("factory::get(): " + name + " object doesn't exist in factory"); } return it->second.get(); } Create your own version of gtest_main.cc implementation. Call factory::create() method to create all SystemC signals and SystemC modules before running any tests RUN_ALL_TESTS(). Because factory class is a singleton design pattern, call factory::destroy() method after finishing all tests to destroy all created SystemC objects. main.cpp #include "factory.hpp" #include <systemc> #include <gtest/gtest.h> int sc_main(int argc, char* argv[]) { factory::get_instance().create(); testing::InitGoogleTest(&argc, argv); int status = RUN_ALL_TESTS(); factory::get_instance().destroy(); return status; } Then define dut class in your test than will create SystemC signals and SystemC modules. In constructor do connection between created SystemC signals and modules. Register defined dut class to registry object using global constructor like this factory::add<dut> g. After than you can get your dut object using simple factory::get<dut>() method. test.cpp #include "my_module.h" #include "factory.hpp" #include <gtest/gtest.h> #include <systemc> class dut { public: sc_core::sc_clock aclk{"aclk"}; sc_core::sc_signal<bool> areset_n{"areset_n"}; sc_core::sc_signal<bool> in{"in"}; sc_core::sc_signal<bool> out{"out"}; dut() { m_dut.aclk(aclk); m_dut.areset_n(areset_n); m_dut.in(in); m_dut.out(out); } private: my_module m_dut{"my_module"}; }; static factory::add<dut> g; TEST(my_module, simple) { auto test = factory::get<dut>(); test->areset_n = 0; test->in = 0; sc_start(3, SC_NS); test->areset_n = 1; test->in = 1; sc_start(3, SC_NS); EXPECT_TRUE(test->out.read()); } For more inspiration, you can check my logic library for SystemC verification: https://github.com/tymonx/logic
    1 point
×
×
  • Create New...