17#ifndef _SYSC_REGISTER_H_
18#define _SYSC_REGISTER_H_
24#include "resource_access_if.h"
25#include "scc/report.h"
26#include <cci_configuration>
27#include <scc/traceable.h>
28#include <scc/tracer_base.h>
29#include <scc/utilities.h>
30#include <sysc/kernel/sc_object.h>
34#include "util/delegate.h"
46template <typename T, bool = std::is_integral<T>::value>
class helper {};
48template <
typename T>
class helper<T, true> {
51 template <
typename Type>
constexpr Type get_max_uval()
const {
52 return std::numeric_limits<Type>::is_signed ? -1 : std::numeric_limits<Type>::max();
56template <
typename T>
class helper<T, false> {
58 using Type =
typename T::StorageType;
59 template <
typename Type>
constexpr Type get_max_uval()
const {
60 return std::numeric_limits<Type>::is_signed ? -1 : std::numeric_limits<Type>::max();
64template <
typename Type>
constexpr Type get_max_uval() {
65 return std::numeric_limits<Type>::is_signed ? -1 : std::numeric_limits<Type>::max();
82 cci::cci_param<bool> enable_tracing;
83 cci::cci_param<bool> enable_side_effect;
97 DATATYPE
rdmask = get_max_uval<DATATYPE>(), DATATYPE
wrmask = get_max_uval<DATATYPE>())
98 : sc_core::sc_object(nm)
99 , enable_tracing{std::string(name()) +
".enableTracing",
scc::
tracer_base::get_default_trace_enable(),
100 "enables tracing of this register", cci::CCI_ABSOLUTE_NAME}
101 , enable_side_effect{std::string(name()) +
".enableSideEffect", true,
"enables side effect in debug read/write operations",
102 cci::CCI_ABSOLUTE_NAME}
127 char const*
full_name()
const override {
return name(); };
134 size_t size()
const override {
return sizeof(DATATYPE); }
159 bool write(
const uint8_t* data,
size_t length, uint64_t offset, sc_core::sc_time& d)
override {
160 SCC_ASSERT(
"Access out of range" && offset + length <=
sizeof(DATATYPE));
162 auto beg =
reinterpret_cast<uint8_t*
>(&temp) + offset;
163 std::copy(data, data + length, beg);
165 return wr_cb(*
this, temp, d);
180 bool read(uint8_t* data,
size_t length, uint64_t offset, sc_core::sc_time& d)
const override {
181 SCC_ASSERT(
"Access out of range" && offset + length <=
sizeof(DATATYPE));
184 if(!rd_cb(*
this, temp, d))
188 auto beg =
reinterpret_cast<uint8_t*
>(&temp) + offset;
189 std::copy(beg, beg + length, data);
201 bool write_dbg(
const uint8_t* data,
size_t length, uint64_t offset = 0)
override {
202 if(enable_side_effect.get_value()) {
204 return write(data, length, offset, d);
207 SCC_ASSERT(
"Offset out of range" && offset == 0);
208 if(length !=
sizeof(DATATYPE))
210 storage = *
reinterpret_cast<const DATATYPE*
>(data);
222 bool read_dbg(uint8_t* data,
size_t length, uint64_t offset = 0)
const override {
223 if(enable_side_effect.get_value()) {
225 return read(data, length, offset, d);
228 SCC_ASSERT(
"Offset out of range" && offset == 0);
229 if(length !=
sizeof(DATATYPE))
231 *
reinterpret_cast<DATATYPE*
>(data) = storage;
239 operator DATATYPE()
const {
return storage; }
246 DATATYPE
get()
const {
return storage; }
253 void put(DATATYPE data)
const { storage = data; }
293 void set_read_cb(std::function<
bool(
const this_type&, DATATYPE&)> read_cb) {
294 rd_cb = [read_cb](
const this_type& reg, DATATYPE& data, sc_core::sc_time& delay) {
return read_cb(reg, data); };
303 void set_read_cb(std::function<
bool(
const this_type&, DATATYPE&, sc_core::sc_time&)> read_cb) { rd_cb = read_cb; }
312 void set_write_cb(std::function<
bool(this_type&,
const DATATYPE&)> write_cb) {
313 wr_cb = [write_cb](this_type& reg, DATATYPE& data, sc_core::sc_time& delay) {
return write_cb(reg, data); };
322 void set_write_cb(std::function<
bool(this_type&,
const DATATYPE&, sc_core::sc_time&)> write_cb) { wr_cb = write_cb; }
329 void trace(sc_core::sc_trace_file* trf)
const override { sc_core::sc_trace(trf, storage, this->name()); }
338 const char* kind()
const override {
return "sc_register"; }
341 std::function<bool(
const this_type&, DATATYPE&, sc_core::sc_time&)> rd_cb;
342 std::function<bool(this_type&, DATATYPE&, sc_core::sc_time&)> wr_cb;
345 std::function<bool(
const this_type&, DATATYPE&, sc_core::sc_time&)> rd_dlgt;
346 std::function<bool(this_type&, DATATYPE&, sc_core::sc_time&)> wr_dlgt;
348 util::delegate<bool(
const this_type&, DATATYPE&, sc_core::sc_time&)> rd_dlgt;
349 util::delegate<bool(this_type&, DATATYPE&, sc_core::sc_time&)> wr_dlgt;
363 using pointer = value_type*;
375 sc_core::sc_module_name nm, std::array<DATATYPE, SIZE>& storage,
const DATATYPE reset_val,
resetable& owner,
376 BASE_DATA_TYPE rdmask = std::numeric_limits<BASE_DATA_TYPE>::is_signed ? -1 : std::numeric_limits<BASE_DATA_TYPE>::max(),
377 BASE_DATA_TYPE wrmask = std::numeric_limits<BASE_DATA_TYPE>::is_signed ? -1 : std::numeric_limits<BASE_DATA_TYPE>::max()) {
379 _reg_field.init(START + SIZE, [&](
const char* name,
size_t idx) -> pointer {
393 size_t size()
override {
return SIZE; };
402 for(
size_t idx = START; idx < SIZE + START; ++idx)
411 rd_time_cb = read_cb;
412 for(
size_t idx = START; idx < SIZE + START; ++idx)
414 return this->rd_time_cb(idx, reg, dt, delay);
425 for(
size_t idx = START; idx < SIZE + START; ++idx)
434 wr_time_cb = write_cb;
435 for(
size_t idx = START; idx < SIZE + START; ++idx)
437 return this->wr_time_cb(idx, reg, dt, delay);
446 reference
operator[](
size_t idx)
noexcept override {
return _reg_field[idx]; }
453 const_reference
operator[](
size_t idx)
const noexcept override {
return _reg_field[idx]; }
460 reference
at(
size_t idx)
override {
461 assert(
"access out of bound" && idx < SIZE);
462 return _reg_field[idx];
470 const_reference
at(
size_t idx)
const override {
471 assert(
"access out of bound" && idx < SIZE);
472 return _reg_field[idx];
476 sc_core::sc_vector<value_type> _reg_field;
485template <typename DATATYPE, DATATYPE WRMASK = impl::get_max_uval<DATATYPE>(), DATATYPE RDMASK = impl::get_max_uval<DATATYPE>()>
488 sc_register_masked(sc_core::sc_module_name nm, DATATYPE& storage,
const DATATYPE reset_val,
resetable& owner)
497 using store_t = DATATYPE;
501 ~mem_wrapper() =
default;
502 char const*
full_name()
const override {
return "memory"; };
503 std::size_t
size()
const override {
return sizeof(DATATYPE); };
504 void reset()
override { elem = 0; };
505 bool write(
const uint8_t* data, std::size_t length, uint64_t offset, sc_core::sc_time& d)
override {
506 assert(
"Access out of range" && offset + length <=
sizeof(DATATYPE));
508 auto beg =
reinterpret_cast<uint8_t*
>(&temp) + offset;
509 std::copy(data, data + length, beg);
511 return owner.wr_cb(owner, this->offset + offset, temp, d);
515 bool read(uint8_t* data, std::size_t length, uint64_t offset, sc_core::sc_time& d)
const override {
516 assert(
"Access out of range" && offset + length <=
sizeof(DATATYPE));
519 if(!owner.rd_cb(owner, this->offset + offset, temp, d))
522 auto beg =
reinterpret_cast<uint8_t*
>(&temp) + offset;
523 std::copy(beg, beg + length, data);
526 bool write_dbg(
const uint8_t* data, std::size_t length, uint64_t offset = 0)
override {
527 assert(
"Offset out of range" && offset == 0);
528 if(length !=
sizeof(DATATYPE))
530 elem = *
reinterpret_cast<const DATATYPE*
>(data);
533 bool read_dbg(uint8_t* data, std::size_t length, uint64_t offset = 0)
const override {
534 assert(
"Offset out of range" && offset == 0);
535 if(length !=
sizeof(DATATYPE))
537 *
reinterpret_cast<DATATYPE*
>(data) = elem;
563 _reg_field.init(SIZE,
564 [
this, &storage](
const char* name,
size_t idx) -> pointer {
return new mem_wrapper(*
this, storage[idx], idx); });
575 size_t size()
override {
return SIZE; };
582 reference
operator[](
size_t idx)
noexcept override {
return _reg_field[idx]; }
589 const_reference
operator[](
size_t idx)
const noexcept override {
return _reg_field[idx]; }
596 reference
at(
size_t idx)
override {
597 assert(
"access out of bound" && idx < SIZE);
598 return _reg_field[idx];
606 const_reference
const at(
size_t idx)
const override {
607 assert(
"access out of bound" && idx < SIZE);
608 return _reg_field[idx];
617 void set_read_cb(std::function<
bool(
const this_type&,
size_t offset, DATATYPE&, sc_core::sc_time&)> read_cb) { rd_cb = read_cb; }
625 void set_write_cb(std::function<
bool(this_type&,
size_t offset,
const DATATYPE&, sc_core::sc_time&)> write_cb) { wr_cb = write_cb; }
628 sc_core::sc_vector<value_type> _reg_field;
629 std::function<bool(
const this_type&,
size_t offset, DATATYPE&, sc_core::sc_time&)> rd_cb;
630 std::function<bool(this_type&,
size_t offset, DATATYPE&, sc_core::sc_time&)> wr_cb;
a simple register implementation
void reset() override
reset the register
void set_write_cb(std::function< bool(this_type &, const DATATYPE &)> write_cb)
set the write callback
void set_read_cb(std::function< bool(const this_type &, DATATYPE &)> read_cb)
set the read callback
bool read_dbg(uint8_t *data, size_t length, uint64_t offset=0) const override
debug read function from resource_access_if
DATATYPE get() const
get the underlying storage
bool read(uint8_t *data, size_t length, uint64_t offset, sc_core::sc_time &d) const override
read function from resource_access_if
void put(DATATYPE data) const
write to the underlying storage
this_type & operator&=(DATATYPE other)
unary and
this_type & operator|=(DATATYPE other)
unary or
bool write_dbg(const uint8_t *data, size_t length, uint64_t offset=0) override
debug write function from resource_access_if
void trace(sc_core::sc_trace_file *trf) const override
trace the register value to the given trace file
void set_read_cb(std::function< bool(const this_type &, DATATYPE &, sc_core::sc_time &)> read_cb)
set the read callback
bool is_trace_enabled() const override
returns of this component shall be traced
sc_register(sc_core::sc_module_name nm, DATATYPE &storage, const DATATYPE reset_val, resetable &owner, DATATYPE rdmask=get_max_uval< DATATYPE >(), DATATYPE wrmask=get_max_uval< DATATYPE >())
the constructor
void set_write_cb(std::function< bool(this_type &, const DATATYPE &, sc_core::sc_time &)> write_cb)
set the write callback triggered upon a write request
~sc_register()=default
desctructor
char const * full_name() const override
return the name of the resource
this_type & operator=(DATATYPE other)
assignment operator
size_t size() const override
get the size of this register in bytes
bool write(const uint8_t *data, size_t length, uint64_t offset, sc_core::sc_time &d) override
write function from resource_access_if
interface defining access to an indexed resource e.g. register file
base class for components having a reset
void register_resource(resource_access_if *res)
register a resource with this reset domain
interface defining access to a resource e.g. a register
virtual std::size_t size() const =0
return the size of the resource
virtual void reset()=0
reset the resource
virtual char const * full_name() const =0
return the name of the resource
const_reference operator[](size_t idx) const noexcept override
void set_write_cb(std::function< bool(size_t, sc_register< DATATYPE > &, DATATYPE const &, sc_core::sc_time &)> write_cb)
reference operator[](size_t idx) noexcept override
void set_read_cb(std::function< bool(size_t, const sc_register< DATATYPE > &, DATATYPE &)> read_cb)
sc_register_indexed(sc_core::sc_module_name nm, std::array< DATATYPE, SIZE > &storage, const DATATYPE reset_val, resetable &owner, BASE_DATA_TYPE rdmask=std::numeric_limits< BASE_DATA_TYPE >::is_signed ? -1 :std::numeric_limits< BASE_DATA_TYPE >::max(), BASE_DATA_TYPE wrmask=std::numeric_limits< BASE_DATA_TYPE >::is_signed ? -1 :std::numeric_limits< BASE_DATA_TYPE >::max())
const_reference at(size_t idx) const override
void set_write_cb(std::function< bool(size_t, sc_register< DATATYPE > &, DATATYPE const &)> write_cb)
~sc_register_indexed() override
reference at(size_t idx) override
void set_read_cb(std::function< bool(size_t, const sc_register< DATATYPE > &, DATATYPE &, sc_core::sc_time &)> read_cb)
impl::sc_register< typename impl::helper< DATATYPE >::Type > sc_register
import the implementation into the scc namespace
void set_write_cb(std::function< bool(this_type &, size_t offset, const DATATYPE &, sc_core::sc_time &)> write_cb)
set the write callback triggered upon a write request
const_reference const at(size_t idx) const override
const_reference operator[](size_t idx) const noexcept override
sc_register_mem(sc_core::sc_module_name nm, std::array< DATATYPE, SIZE > &storage, const DATATYPE reset_val, resetable &owner)
~sc_register_mem() override
reference operator[](size_t idx) noexcept override
void set_read_cb(std::function< bool(const this_type &, size_t offset, DATATYPE &, sc_core::sc_time &)> read_cb)
set the read callback
reference at(size_t idx) override
base class for automatic tracer