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>
33#include "util/delegate.h"
45template <typename T, bool = std::is_integral<T>::value>
class helper {};
47template <
typename T>
class helper<T, true> {
50 template <
typename Type>
constexpr Type get_max_uval()
const {
51 return std::numeric_limits<Type>::is_signed ? -1 : std::numeric_limits<Type>::max();
55template <
typename T>
class helper<T, false> {
57 using Type =
typename T::StorageType;
58 template <
typename Type>
constexpr Type get_max_uval()
const {
59 return std::numeric_limits<Type>::is_signed ? -1 : std::numeric_limits<Type>::max();
63template <
typename Type>
constexpr Type get_max_uval() {
64 return std::numeric_limits<Type>::is_signed ? -1 : std::numeric_limits<Type>::max();
81 cci::cci_param<bool> enable_tracing;
95 DATATYPE
rdmask = get_max_uval<DATATYPE>(), DATATYPE
wrmask = get_max_uval<DATATYPE>())
96 : sc_core::sc_object(nm)
97 , enable_tracing{std::string(name()) +
".enableTracing",
scc::
tracer_base::get_default_trace_enable(),
98 "enables tracing of this register", cci::CCI_ABSOLUTE_NAME}
124 size_t size()
const override {
return sizeof(DATATYPE); }
149 bool write(
const uint8_t* data,
size_t length, uint64_t offset, sc_core::sc_time& d)
override {
150 SCC_ASSERT(
"Access out of range" && offset + length <=
sizeof(DATATYPE));
152 auto beg =
reinterpret_cast<uint8_t*
>(&temp) + offset;
153 std::copy(data, data + length, beg);
155 return wr_cb(*
this, temp, d);
170 bool read(uint8_t* data,
size_t length, uint64_t offset, sc_core::sc_time& d)
const override {
171 SCC_ASSERT(
"Access out of range" && offset + length <=
sizeof(DATATYPE));
174 if(!rd_cb(*
this, temp, d))
178 auto beg =
reinterpret_cast<uint8_t*
>(&temp) + offset;
179 std::copy(beg, beg + length, data);
193 bool write_dbg(
const uint8_t* data,
size_t length, uint64_t offset = 0)
override {
194 SCC_ASSERT(
"Offset out of range" && offset == 0);
195 if(length !=
sizeof(DATATYPE))
197 storage = *
reinterpret_cast<const DATATYPE*
>(data);
211 bool read_dbg(uint8_t* data,
size_t length, uint64_t offset = 0)
const override {
212 SCC_ASSERT(
"Offset out of range" && offset == 0);
213 if(length !=
sizeof(DATATYPE))
215 *
reinterpret_cast<DATATYPE*
>(data) = storage;
223 operator DATATYPE()
const {
return storage; }
230 DATATYPE
get()
const {
return storage; }
237 void put(DATATYPE data)
const { storage = data; }
277 void set_read_cb(std::function<
bool(
const this_type&, DATATYPE&)> read_cb) {
278 rd_cb = [read_cb](
const this_type& reg, DATATYPE& data, sc_core::sc_time& delay) {
return read_cb(reg, data); };
287 void set_read_cb(std::function<
bool(
const this_type&, DATATYPE&, sc_core::sc_time&)> read_cb) { rd_cb = read_cb; }
296 void set_write_cb(std::function<
bool(this_type&,
const DATATYPE&)> write_cb) {
297 wr_cb = [write_cb](this_type& reg, DATATYPE& data, sc_core::sc_time& delay) {
return write_cb(reg, data); };
306 void set_write_cb(std::function<
bool(this_type&,
const DATATYPE&, sc_core::sc_time&)> write_cb) { wr_cb = write_cb; }
313 void trace(sc_core::sc_trace_file* trf)
const override { sc_core::sc_trace(trf, storage, this->name()); }
322 const char* kind()
const override {
return "sc_register"; }
325 std::function<bool(
const this_type&, DATATYPE&, sc_core::sc_time&)> rd_cb;
326 std::function<bool(this_type&, DATATYPE&, sc_core::sc_time&)> wr_cb;
329 std::function<bool(
const this_type&, DATATYPE&, sc_core::sc_time&)> rd_dlgt;
330 std::function<bool(this_type&, DATATYPE&, sc_core::sc_time&)> wr_dlgt;
332 util::delegate<bool(
const this_type&, DATATYPE&, sc_core::sc_time&)> rd_dlgt;
333 util::delegate<bool(this_type&, DATATYPE&, sc_core::sc_time&)> wr_dlgt;
347 using pointer = value_type*;
359 sc_core::sc_module_name nm, std::array<DATATYPE, SIZE>& storage,
const DATATYPE reset_val,
resetable& owner,
360 BASE_DATA_TYPE rdmask = std::numeric_limits<BASE_DATA_TYPE>::is_signed ? -1 : std::numeric_limits<BASE_DATA_TYPE>::max(),
361 BASE_DATA_TYPE wrmask = std::numeric_limits<BASE_DATA_TYPE>::is_signed ? -1 : std::numeric_limits<BASE_DATA_TYPE>::max()) {
363 _reg_field.init(START + SIZE, [&](
const char* name,
size_t idx) -> pointer {
377 size_t size()
override {
return SIZE; };
386 for(
size_t idx = START; idx < SIZE + START; ++idx)
395 rd_time_cb = read_cb;
396 for(
size_t idx = START; idx < SIZE + START; ++idx)
398 return this->rd_time_cb(idx, reg, dt, delay);
409 for(
size_t idx = START; idx < SIZE + START; ++idx)
418 wr_time_cb = write_cb;
419 for(
size_t idx = START; idx < SIZE + START; ++idx)
421 return this->wr_time_cb(idx, reg, dt, delay);
430 reference
operator[](
size_t idx)
noexcept override {
return _reg_field[idx]; }
437 const_reference
operator[](
size_t idx)
const noexcept override {
return _reg_field[idx]; }
444 reference
at(
size_t idx)
override {
445 assert(
"access out of bound" && idx < SIZE);
446 return _reg_field[idx];
454 const_reference
at(
size_t idx)
const override {
455 assert(
"access out of bound" && idx < SIZE);
456 return _reg_field[idx];
460 sc_core::sc_vector<value_type> _reg_field;
469template <typename DATATYPE, DATATYPE WRMASK = impl::get_max_uval<DATATYPE>(), DATATYPE RDMASK = impl::get_max_uval<DATATYPE>()>
472 sc_register_masked(sc_core::sc_module_name nm, DATATYPE& storage,
const DATATYPE reset_val,
resetable& owner)
481 using store_t = DATATYPE;
485 ~mem_wrapper() =
default;
486 std::size_t
size()
const override {
return sizeof(DATATYPE); };
487 void reset()
override { elem = 0; };
488 bool write(
const uint8_t* data, std::size_t length, uint64_t offset, sc_core::sc_time& d)
override {
489 assert(
"Access out of range" && offset + length <=
sizeof(DATATYPE));
491 auto beg =
reinterpret_cast<uint8_t*
>(&temp) + offset;
492 std::copy(data, data + length, beg);
494 return owner.wr_cb(owner, this->offset + offset, temp, d);
498 bool read(uint8_t* data, std::size_t length, uint64_t offset, sc_core::sc_time& d)
const override {
499 assert(
"Access out of range" && offset + length <=
sizeof(DATATYPE));
502 if(!owner.rd_cb(owner, this->offset + offset, temp, d))
505 auto beg =
reinterpret_cast<uint8_t*
>(&temp) + offset;
506 std::copy(beg, beg + length, data);
509 bool write_dbg(
const uint8_t* data, std::size_t length, uint64_t offset = 0)
override {
510 assert(
"Offset out of range" && offset == 0);
511 if(length !=
sizeof(DATATYPE))
513 elem = *
reinterpret_cast<const DATATYPE*
>(data);
516 bool read_dbg(uint8_t* data, std::size_t length, uint64_t offset = 0)
const override {
517 assert(
"Offset out of range" && offset == 0);
518 if(length !=
sizeof(DATATYPE))
520 *
reinterpret_cast<DATATYPE*
>(data) = elem;
546 _reg_field.init(SIZE,
547 [
this, &storage](
const char* name,
size_t idx) -> pointer {
return new mem_wrapper(*
this, storage[idx], idx); });
558 size_t size()
override {
return SIZE; };
565 reference
operator[](
size_t idx)
noexcept override {
return _reg_field[idx]; }
572 const_reference
operator[](
size_t idx)
const noexcept override {
return _reg_field[idx]; }
579 reference
at(
size_t idx)
override {
580 assert(
"access out of bound" && idx < SIZE);
581 return _reg_field[idx];
589 const_reference
const at(
size_t idx)
const override {
590 assert(
"access out of bound" && idx < SIZE);
591 return _reg_field[idx];
600 void set_read_cb(std::function<
bool(
const this_type&,
size_t offset, DATATYPE&, sc_core::sc_time&)> read_cb) { rd_cb = read_cb; }
608 void set_write_cb(std::function<
bool(this_type&,
size_t offset,
const DATATYPE&, sc_core::sc_time&)> write_cb) { wr_cb = write_cb; }
611 sc_core::sc_vector<value_type> _reg_field;
612 std::function<bool(
const this_type&,
size_t offset, DATATYPE&, sc_core::sc_time&)> rd_cb;
613 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
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
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