17 #ifndef _SYSC_REGISTER_H_
18 #define _SYSC_REGISTER_H_
22 #include "resetable.h"
23 #include "resource_access_if.h"
24 #include "scc/traceable.h"
25 #include "scc/utilities.h"
29 #include "util/delegate.h"
41 template <typename T, bool = std::is_integral<T>::value>
class helper {};
43 template <
typename T>
class helper<T, true> {
46 template <
typename Type> constexpr Type get_max_uval()
const {
47 return std::numeric_limits<Type>::is_signed ? -1 : std::numeric_limits<Type>::max();
51 template <
typename T>
class helper<T, false> {
53 using Type =
typename T::StorageType;
54 template <
typename Type> constexpr Type get_max_uval()
const {
55 return std::numeric_limits<Type>::is_signed ? -1 : std::numeric_limits<Type>::max();
59 template <
typename Type> constexpr Type get_max_uval() {
60 return std::numeric_limits<Type>::is_signed ? -1 : std::numeric_limits<Type>::max();
89 DATATYPE
rdmask = get_max_uval<DATATYPE>(), DATATYPE
wrmask = get_max_uval<DATATYPE>())
90 : sc_core::sc_object(nm)
95 owner.register_resource(
this);
109 size_t size()
const override {
return sizeof(DATATYPE); }
134 bool write(
const uint8_t* data,
size_t length, uint64_t offset, sc_core::sc_time& d)
override {
135 assert(
"Access out of range" && offset + length <=
sizeof(DATATYPE));
137 auto beg =
reinterpret_cast<uint8_t*
>(&temp) + offset;
138 std::copy(data, data + length, beg);
140 return wr_cb(*
this, temp, d);
155 bool read(uint8_t* data,
size_t length, uint64_t offset, sc_core::sc_time& d)
const override {
156 assert(
"Access out of range" && offset + length <=
sizeof(DATATYPE));
159 if(!rd_cb(*
this, temp, d))
163 auto beg =
reinterpret_cast<uint8_t*
>(&temp) + offset;
164 std::copy(beg, beg + length, data);
178 bool write_dbg(
const uint8_t* data,
size_t length, uint64_t offset = 0)
override {
179 assert(
"Offset out of range" && offset == 0);
180 if(length !=
sizeof(DATATYPE))
182 storage = *
reinterpret_cast<const DATATYPE*
>(data);
196 bool read_dbg(uint8_t* data,
size_t length, uint64_t offset = 0)
const override {
197 assert(
"Offset out of range" && offset == 0);
198 if(length !=
sizeof(DATATYPE))
200 *
reinterpret_cast<DATATYPE*
>(data) = storage;
208 operator DATATYPE()
const {
return storage; }
215 DATATYPE
get()
const {
return storage; }
222 void put(DATATYPE data)
const { storage = data; }
266 rd_cb = [read_cb](
const this_type& reg, DATATYPE& data, sc_core::sc_time& delay) {
return read_cb(reg, data); };
276 void set_read_cb(std::function<
bool(
const this_type&, DATATYPE&, sc_core::sc_time&)> read_cb) { rd_cb = read_cb; }
287 wr_cb = [write_cb](
this_type& reg, DATATYPE& data, sc_core::sc_time& delay) {
return write_cb(reg, data); };
302 void set_write_cb(std::function<
bool(
this_type&,
const DATATYPE&, sc_core::sc_time&)> write_cb) { wr_cb = write_cb; }
309 void trace(sc_core::sc_trace_file* trf)
const override { sc_core::sc_trace(trf, storage, this->name()); }
318 const char* kind()
const override {
return "sc_register"; }
321 std::function<bool(
const this_type&, DATATYPE&, sc_core::sc_time&)> rd_cb;
322 std::function<bool(this_type&, DATATYPE&, sc_core::sc_time&)> wr_cb;
325 std::function<bool(
const this_type&, DATATYPE&, sc_core::sc_time&)> rd_dlgt;
326 std::function<bool(this_type&, DATATYPE&, sc_core::sc_time&)> wr_dlgt;
328 util::delegate<bool(
const this_type&, DATATYPE&, sc_core::sc_time&)> rd_dlgt;
329 util::delegate<bool(this_type&, DATATYPE&, sc_core::sc_time&)> wr_dlgt;
355 sc_core::sc_module_name nm, std::array<DATATYPE, SIZE>& storage,
const DATATYPE reset_val,
resetable& owner,
356 BASE_DATA_TYPE rdmask = std::numeric_limits<BASE_DATA_TYPE>::is_signed ? -1 : std::numeric_limits<BASE_DATA_TYPE>::max(),
357 BASE_DATA_TYPE wrmask = std::numeric_limits<BASE_DATA_TYPE>::is_signed ? -1 : std::numeric_limits<BASE_DATA_TYPE>::max()) {
359 _reg_field.init(START + SIZE, [&](
const char* name,
size_t idx) ->
pointer {
373 size_t size()
override {
return SIZE; };
382 for(
size_t idx = START; idx < SIZE + START; ++idx)
391 rd_time_cb = read_cb;
392 for(
size_t idx = START; idx < SIZE + START; ++idx)
394 return this->rd_time_cb(idx, reg, dt, delay);
405 for(
size_t idx = START; idx < SIZE + START; ++idx)
414 wr_time_cb = write_cb;
415 for(
size_t idx = START; idx < SIZE + START; ++idx)
417 return this->wr_time_cb(idx, reg, dt, delay);
441 assert(
"access out of bound" && idx < SIZE);
442 return _reg_field[idx];
451 assert(
"access out of bound" && idx < SIZE);
452 return _reg_field[idx];
456 sc_core::sc_vector<value_type> _reg_field;
460 std::function<bool(
size_t,
sc_register<DATATYPE> const&, DATATYPE
const&, sc_core::sc_time&)> rd_time_cb;
465 template <typename DATATYPE, DATATYPE WRMASK = impl::get_max_uval<DATATYPE>(), DATATYPE RDMASK = impl::get_max_uval<DATATYPE>()>
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
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
const DATATYPE wrmask
the SW write mask
void set_write_cb(std::function< bool(this_type &, const DATATYPE &, sc_core::sc_time &)> write_cb)
~sc_register()=default
desctructor
const DATATYPE rdmask
the SW read mask
const DATATYPE res_val
the reset value
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
interface defining access to a resource e.g. a register
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)
interface defining a traceable component