24 #ifndef __SCC_TLM_TARGET_BFS_REGISTER_BASE_H__
25 #define __SCC_TLM_TARGET_BFS_REGISTER_BASE_H__
33 #include <boost/preprocessor/arithmetic/add.hpp>
34 #include <boost/preprocessor/arithmetic/mul.hpp>
35 #include <boost/preprocessor/cat.hpp>
36 #include <boost/preprocessor/facilities/overload.hpp>
37 #include <boost/preprocessor/punctuation/comma_if.hpp>
38 #include <boost/preprocessor/repetition/repeat.hpp>
39 #include <boost/preprocessor/stringize.hpp>
40 #include <boost/preprocessor/tuple/elem.hpp>
42 #include "resetable.h"
43 #include "resource_access_if.h"
44 #include "sysc/kernel/sc_module_name.h"
45 #include "sysc/kernel/sc_object.h"
46 #include "tlm_target.h"
48 #define ID_SCC_TLM_TARGET_BFS_REGISTER_BASE "scc: tlm target bitfield support register base"
59 constexpr
abstract_bitfield(std::string name,
size_t bitOffset,
size_t bitSize, std::string urid)
60 : bitOffset{bitOffset}
62 , name{std::move(name)}
63 , urid{std::move(urid)} {}
65 virtual void write(datatype_t& valueToWrite) = 0;
66 virtual datatype_t read() = 0;
69 constexpr
bool affected(
size_t byteOffset,
size_t byteLength)
const noexcept {
70 return (byteOffset * 8 < bitOffset + bitSize) && (bitOffset < (byteOffset + byteLength) * 8);
73 constexpr datatype_t mask()
const noexcept {
return ((1ULL << bitSize) - 1) << bitOffset; }
75 const size_t bitOffset;
77 const std::string name;
78 const std::string urid;
99 constexpr
bitfield_register(sc_core::sc_module_name name,
size_t offset, datatype_t resetValue = 0, datatype_t writeMask = -1,
100 datatype_t readMask = -1)
101 : sc_core::sc_object{name}
103 , resetValue{resetValue}
104 , writeMask{writeMask}
105 , readMask{readMask} {}
110 constexpr
size_t size() const noexcept
override {
return sizeof(datatype_t); }
112 void reset()
override { storage = resetValue; }
114 bool write(
const uint8_t* data, std::size_t length, uint64_t offset, sc_core::sc_time& d)
override {
115 assert(
"Access out of range" && offset + length <= this->
size());
116 auto valueToWrite{storage};
117 std::copy(data, data + length,
reinterpret_cast<uint8_t*
>(&valueToWrite) + offset);
118 for(
auto&& bitfield : bitfields) {
119 if(bitfield.get().affected(offset, length)) {
120 auto mask = bitfield.get().mask();
121 auto bits = (valueToWrite & mask) >> bitfield.get().bitOffset;
122 bitfield.get().write(bits);
123 valueToWrite = (valueToWrite & ~mask) | ((bits << bitfield.get().bitOffset) & mask);
127 writeCallback(*
this, valueToWrite);
128 storage = (valueToWrite & writeMask) | (storage & ~writeMask);
132 bool read(uint8_t* data, std::size_t length, uint64_t offset, sc_core::sc_time& d)
const override {
133 assert(
"Access out of range" && offset + length <= this->
size());
134 auto result{storage};
136 for(
auto&& bitfield : bitfields) {
137 if(bitfield.get().affected(offset, length)) {
138 auto bitfieldValue = bitfield.get().read();
139 auto mask = bitfield.get().mask();
140 result = (result & ~mask) | ((bitfieldValue << bitfield.get().bitOffset) & mask);
144 readCallback(*
this, result);
145 auto begin =
reinterpret_cast<const uint8_t*
>(&result) + offset;
146 std::copy(begin, begin + length, data);
150 bool write_dbg(
const uint8_t* data, std::size_t length, uint64_t offset = 0)
override {
151 assert(
"Offset out of range" && offset == 0);
152 if(length != this->
size())
154 std::copy(data, data + length,
reinterpret_cast<uint8_t*
>(&storage));
158 bool read_dbg(uint8_t* data, std::size_t length, uint64_t offset = 0)
const override {
159 assert(
"Offset out of range" && offset == 0);
160 if(length != this->
size())
162 auto storagePtr =
reinterpret_cast<const uint8_t*
>(&storage);
163 std::copy(storagePtr, storagePtr + length, data);
170 constexpr datatype_t
get()
const {
return storage; }
174 void put(datatype_t value) { storage = value; }
181 constexpr
operator datatype_t()
const {
return storage; }
202 writeCallback = std::move(callback);
212 readCallback = std::move(callback);
218 const datatype_t resetValue;
219 const datatype_t writeMask;
220 const datatype_t readMask;
225 std::vector<std::reference_wrapper<abstract_bitfield<datatype_t>>> bitfields;
230 enum Access { RW, ReadOnly };
246 ,
abstract_bitfield<datatype_t>{std::move(name), bitOffset, bitSize, std::move(urid)}
248 reg.registerBitfield(*
this);
253 void write(datatype_t& valueToWrite)
override {
255 writeCallback(*
this, valueToWrite);
256 if(access == ReadOnly)
257 valueToWrite =
get();
259 datatype_t read()
override {
261 return readCallback(*
this);
269 constexpr datatype_t
get()
const {
return (reg.get() & mask()) >> bitOffset; }
273 void put(datatype_t value) { reg.put((reg.get() & ~mask()) | ((value << bitOffset) & mask())); }
278 constexpr
operator datatype_t()
const {
return get(); }
299 writeCallback = std::move(callback);
329 : sc_core::sc_object{name} {}
332 for(
auto&& reg : asDerived().registers) {
344 auto found = std::find_if(asDerived().registers.begin(), asDerived().registers.end(),
346 if(found == asDerived().registers.end()) {
347 SC_REPORT_FATAL(ID_SCC_TLM_TARGET_BFS_REGISTER_BASE, (
"Register " + name +
" not found").c_str());
361 std::find_if(asDerived().bitfields.begin(), asDerived().bitfields.end(), [regname, name](
const bitfield<uint32_t>& bf) {
362 return regname.compare(bf.reg.basename()) == 0 && name == bf.name;
364 if(found == asDerived().bitfields.end()) {
365 SC_REPORT_FATAL(ID_SCC_TLM_TARGET_BFS_REGISTER_BASE, (
"Bitfield " + name +
" in register " + regname +
" not found").c_str());
377 auto found = std::find_if(asDerived().bitfields.begin(), asDerived().bitfields.end(),
379 if(found == asDerived().bitfields.end()) {
380 SC_REPORT_FATAL(ID_SCC_TLM_TARGET_BFS_REGISTER_BASE, (
"Bitfield with urid " + urid +
" not found").c_str());
400 if(result.urid != urid) {
401 SC_REPORT_WARNING(ID_SCC_TLM_TARGET_BFS_REGISTER_BASE,
402 (
"URID of register is " + result.urid +
" but " + urid +
" was passed").c_str());
409 derived_t& asDerived() {
return static_cast<derived_t&
>(*this); }
425 #define BITFIELD_ARRAY_ELEMENT(z, i, elem) \
426 BOOST_PP_COMMA_IF(i) { \
427 getRegister(BOOST_PP_TUPLE_ELEM(0, elem)), \
428 BOOST_PP_TUPLE_ELEM(1, elem) \
429 BOOST_PP_STRINGIZE(i), BOOST_PP_TUPLE_ELEM(2, elem) + i *BOOST_PP_TUPLE_ELEM(3, elem), BOOST_PP_TUPLE_ELEM(3, elem), \
430 BOOST_PP_TUPLE_ELEM(4, elem) BOOST_PP_STRINGIZE(i) BOOST_PP_TUPLE_ELEM(5, elem) \
449 #define BITFIELD_ARRAY(regname, basename, offset, size, uridbase, count) \
450 BOOST_PP_REPEAT(count, BITFIELD_ARRAY_ELEMENT, (regname, basename, offset, size, uridbase, ))
459 #define BITFIELD_ARRAY_POSTFIX(regname, basename, offset, size, uridbase, uridpostfix, count) \
460 BOOST_PP_REPEAT(count, BITFIELD_ARRAY_ELEMENT, (regname, basename, offset, size, uridbase, uridpostfix))
473 #define REGISTER_ARRAY_ELEMENT(z, i, elem) \
474 BOOST_PP_COMMA_IF(i) { \
475 BOOST_PP_TUPLE_ELEM(0, elem) \
476 BOOST_PP_STRINGIZE(i), BOOST_PP_TUPLE_ELEM(1, elem) + i* BOOST_PP_TUPLE_ELEM(2, elem) \
493 #define REGISTER_ARRAY(basename, offset, size, count) BOOST_PP_REPEAT(count, REGISTER_ARRAY_ELEMENT, (basename, offset, size))
Abstract baseclass for bitfield.
Register that can contain bitfields.
void setWriteCallback(std::function< void(bitfield_register< datatype_t > &, datatype_t &valueToWrite)> callback)
bool write_dbg(const uint8_t *data, std::size_t length, uint64_t offset=0) override
debug write to the resource
constexpr size_t size() const noexcept override
void reset() override
reset the resource
bitfield_register< datatype_t > & operator=(datatype_t other)
bool read_dbg(uint8_t *data, std::size_t length, uint64_t offset=0) const override
debug read the data from the resource
constexpr bitfield_register(sc_core::sc_module_name name, size_t offset, datatype_t resetValue=0, datatype_t writeMask=-1, datatype_t readMask=-1)
constexpr datatype_t get() const
void put(datatype_t value)
void setReadCallback(std::function< void(const bitfield_register< datatype_t > &, datatype_t &result)> callback)
void put(datatype_t value)
void setReadCallback(std::function< datatype_t(const bitfield< datatype_t > &)> callback)
bitfield(bitfield_register< datatype_t > ®, std::string name, size_t bitOffset, size_t bitSize, std::string urid, Access access=RW)
void setWriteCallback(std::function< void(bitfield< datatype_t > &, datatype_t &valueToWrite)> callback)
bitfield< datatype_t > & operator=(datatype_t other)
constexpr datatype_t get() const
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
bitfield_register< uint32_t > & getRegister(const std::string &name)
Search for a register by name.
bitfield< uint32_t > & getBitfieldByName(const std::string ®name, const std::string &name)
Search for a bitfield by name and register name.
bitfield< uint32_t > & getBitfield(const std::string ®name, const std::string &name, const std::string &urid)
Preferred way to get access to a bitfield.
bitfield< uint32_t > & getBitfieldById(const std::string &urid)
Search for a bitfield by urid.
a simple access-width based bus interface (no DMI support)
void addResource(resource_access_if &rai, uint64_t base_addr)
add a resource to this target at a certain address within the socket address range