52 #ifndef ETISS_INTERFACES_WISHBONE_H
53 #define ETISS_INTERFACES_WISHBONE_H
72 template <
typename BOOLSIG>
82 template <
typename BOOLSIG>
91 template <
typename VECTORSIG>
101 template <
typename VECTORSIGSTORAGETYPE,
typename VECTORSIG>
111 template <
typename VECTORSIGSTORAGETYPE,
typename VECTORSIG>
123 template <
typename SELSIG>
130 template <
typename BOOLSIG,
typename VECTORSIG>
151 WishboneSignalMap(BOOLSIG &clk_o, BOOLSIG &ack_i, BOOLSIG &err_i, BOOLSIG &rty_i, BOOLSIG &cyc_o, BOOLSIG &stb_o,
152 BOOLSIG &we_o, BOOLSIG &sel_o, BOOLSIG &bte_o, BOOLSIG &cti_o, VECTORSIG &
dat_i, VECTORSIG &adr_o,
171 template <
typename BOOLSIG,
typename VECTORSIG,
bool instrBus,
bool flipEndianess,
172 unsigned bytewidth =
sizeof(VECTORSIG),
typename VECTORSIGSTORAGETYPE = VECTORSIG>
180 static_assert(bytewidth ==
sizeof(VECTORSIGSTORAGETYPE),
"bytewidth != sizeof(VECTORSIGSTORAGETYPE)");
195 , useposclkedge(
true)
231 if (time <= lastutime)
233 std::cout <<
"Wishbone::update() no time elapsed or time is negative!" << std::endl;
239 if (time + 2 < lastutime)
241 std::cout <<
"Wishbone::update() time is negative! time: " << time / 1000
242 <<
" ns, lastutime: " << lastutime / 1000 <<
" ns"
243 <<
" premain: " << premain <<
" reset: " << reset << std::endl;
249 bool clkedge = (((
bool)lastclock) != (
getBool(core_, sigs.clk_i))) &&
250 ((
getBool(core_, sigs.clk_i)) == ((
bool)useposclkedge));
255 lastclock =
getBool(core_, sigs.clk_i);
273 setBool(core_, sigs.ack_o, !po_err);
274 setBool(core_, sigs.err_o, po_err);
275 setBool(core_, sigs.rty_o,
false);
277 setData<VECTORSIGSTORAGETYPE, VECTORSIG>(core_, sigs.dat_o, dat_o);
280 sigs.ack_o = !po_err;
292 setBool(core_, sigs.ack_o,
false);
293 setBool(core_, sigs.err_o,
false);
294 setBool(core_, sigs.rty_o,
false);
295 setData<VECTORSIGSTORAGETYPE, VECTORSIG>(core_, sigs.dat_o, 0);
300 if (clkedge && (pending == 0))
304 setBool(core_, sigs.ack_o,
false);
305 setBool(core_, sigs.err_o,
false);
306 setBool(core_, sigs.rty_o,
false);
307 setData<VECTORSIGSTORAGETYPE, VECTORSIG>(core_, sigs.dat_o, 0);
312 unsigned addressOffet = addr & (bytewidth - 1);
314 VECTORSIGSTORAGETYPE dataBuf = 0;
320 if (!sel2Length(
getSel(core_, sigs.sel_i), dataLength, addressOffet))
322 std::string(
"invalid sel_i: ") + std::to_string(
getSel(core_, sigs.sel_i)));
323 dataBuf = getData<VECTORSIGSTORAGETYPE, VECTORSIG>(core_, sigs.dat_i);
324 flipEndianness((
uint8_t *)&dataBuf);
325 exception = write(instrBus, localTime, addr + addressOffet,
326 ((
uint8_t *)&dataBuf) + addressOffet, dataLength);
337 if (!sel2Length(
getSel(core_, sigs.sel_i), dataLength, addressOffet))
339 std::string(
"invalid sel_i: ") + std::to_string(
getSel(core_, sigs.sel_i)));
340 exception = read(instrBus, localTime, addr + addressOffet,
341 ((
uint8_t *)&dataBuf) + addressOffet, dataLength);
342 flipEndianness((
uint8_t *)&dataBuf);
353 po_err = (exception == etiss::RETURNCODE::DBUS_READ_ERROR ||
354 exception == etiss::RETURNCODE::DBUS_WRITE_ERROR ||
355 exception == etiss::RETURNCODE::IBUS_READ_ERROR ||
356 exception == etiss::RETURNCODE::IBUS_WRITE_ERROR);
374 for (
unsigned i = 0; i < (bytewidth / 2); ++i)
376 std::swap(buf[i], buf[bytewidth - 1 - i]);
391 unsigned selectOffset = 0;
401 while ((sel & 1) == 0)
409 while ((sel & 1) == 1)
421 selectOffset = bytewidth -
length - selectOffset;
424 static bool output_addressOffset_warning =
false;
425 if ((selectOffset != addressOffset) && !output_addressOffset_warning)
428 std::string(
"Wishbone bus offset not valid! (0x") + std::to_string((
int)addressOffset) +
")");
429 output_addressOffset_warning =
true;
#define static_assert(x, y)
#define etiss_log(LEVEL, MSG)
static __inline__ uint32_t
static __inline__ uint64_t
static __inline__ uint8_t
CPUCore is responsible for the simulation of a CPU core in ETISS.
connects a wishbone bus interface implemented with the variables of WishboneSignalMap to a ETISS_Syst...
bool useposclkedge
use positive or negative clock edge
VECTORSIGSTORAGETYPE dat_o
buffer for data out to CPU
void init()
Initiate all bus output signals and set pending status to "nothing pending".
unsigned pending
0: nothing pending; 1: Read pending; 2: Write pending
WishboneBus(WishboneSignalMap< BOOLSIG, VECTORSIG > &sigs, ETISS_System &system, ETISS_CPU &cpu, etiss::CPUCore &core)
Constructor.
void flipEndianness(uint8_t *buf)
Flips endianess of a VECTORSIG.
bool po_err
bus error arised
bool lastclock
used for determining clock edge
WishboneSignalMap< BOOLSIG, VECTORSIG > & sigs
Signals between bus and CPU.
bool sel2Length(uint32_t sel, unsigned &length, unsigned &addressOffset)
Calculates length and offset out of signal sel.
etiss_int32 update(uint64_t time, bool premain, bool reset, bool posSimTime=true)
Update signals to CPU or read/write from/to bus.
uint64_t lastutime
time of last signal evaluation phase
WishboneSignalMap(BOOLSIG &clk_o, BOOLSIG &ack_i, BOOLSIG &err_i, BOOLSIG &rty_i, BOOLSIG &cyc_o, BOOLSIG &stb_o, BOOLSIG &we_o, BOOLSIG &sel_o, BOOLSIG &bte_o, BOOLSIG &cti_o, VECTORSIG &dat_i, VECTORSIG &adr_o, VECTORSIG &dat_o)
void setData(etiss::CPUCore &core, VECTORSIG &sig, VECTORSIGSTORAGETYPE val)
general helper function to set a signal; needs to be implemented as needed
VECTORSIGSTORAGETYPE getData(etiss::CPUCore &core, VECTORSIG &sig)
general helper function to read a signal; needs to be implemented as needed
uint64_t getAddr(etiss::CPUCore &core, VECTORSIG &sig, bool instrBus)
general helper function to read an address; needs to be implemented as needed
bool getBool(etiss::CPUCore &core, BOOLSIG &sig)
general helper function to read a signal; needs to be implemented as needed
void setBool(etiss::CPUCore &core, BOOLSIG &sig, bool val)
general helper function to set a signal; needs to be implemented as needed
uint32_t getSel(etiss::CPUCore &core, SELSIG &sel_i)
general helper function to read a vector signal; needs to be implemented as needed
MM_EXPORT const int32_t NOERROR
Page Table Entry (PTE) defines the composition of Page Frame Number (PFN) and relavant flags.
void log(Verbosity level, std::string msg)
write log message at the given level.
float __ovld __cnfn length(float p)
Return the length of vector p, i.e., sqrt(p.x2 + p.y 2 + ...)
void swap(T &lhs, T &rhs)
basic cpu state structure needed for execution of any cpu architecture.
memory access and time synchronization functions.
simple helper struct to trigger static_assert only if the template is instantiated