14#ifndef ETISS_INTERFACES_WISHBONE_H
15#define ETISS_INTERFACES_WISHBONE_H
34template <
typename BOOLSIG>
44template <
typename BOOLSIG>
53template <
typename VECTORSIG>
63template <
typename VECTORSIGSTORAGETYPE,
typename VECTORSIG>
73template <
typename VECTORSIGSTORAGETYPE,
typename VECTORSIG>
85template <
typename SELSIG>
92template <
typename BOOLSIG,
typename VECTORSIG>
113 WishboneSignalMap(BOOLSIG &clk_o, BOOLSIG &ack_i, BOOLSIG &err_i, BOOLSIG &rty_i, BOOLSIG &cyc_o, BOOLSIG &stb_o,
114 BOOLSIG &we_o, BOOLSIG &sel_o, BOOLSIG &bte_o, BOOLSIG &cti_o, VECTORSIG &
dat_i, VECTORSIG &adr_o,
133template <
typename BOOLSIG,
typename VECTORSIG,
bool instrBus,
bool flipEndianess,
134 unsigned bytewidth =
sizeof(VECTORSIG),
typename VECTORSIGSTORAGETYPE = VECTORSIG>
142 static_assert(bytewidth ==
sizeof(VECTORSIGSTORAGETYPE),
"bytewidth != sizeof(VECTORSIGSTORAGETYPE)");
157 , useposclkedge(
true)
187 etiss::int32 exception = etiss::RETURNCODE::NOERROR;
193 if (time <= lastutime)
195 std::cout <<
"Wishbone::update() no time elapsed or time is negative!" << std::endl;
201 if (time + 2 < lastutime)
203 std::cout <<
"Wishbone::update() time is negative! time: " << time / 1000
204 <<
" ns, lastutime: " << lastutime / 1000 <<
" ns"
205 <<
" premain: " << premain <<
" reset: " << reset << std::endl;
211 bool clkedge = (((
bool)lastclock) != (
getBool(core_, sigs.clk_i))) &&
212 ((
getBool(core_, sigs.clk_i)) == ((
bool)useposclkedge));
217 lastclock =
getBool(core_, sigs.clk_i);
235 setBool(core_, sigs.ack_o, !po_err);
236 setBool(core_, sigs.err_o, po_err);
237 setBool(core_, sigs.rty_o,
false);
239 setData<VECTORSIGSTORAGETYPE, VECTORSIG>(core_, sigs.dat_o, dat_o);
242 sigs.ack_o = !po_err;
254 setBool(core_, sigs.ack_o,
false);
255 setBool(core_, sigs.err_o,
false);
256 setBool(core_, sigs.rty_o,
false);
257 setData<VECTORSIGSTORAGETYPE, VECTORSIG>(core_, sigs.dat_o, 0);
262 if (clkedge && (pending == 0))
266 setBool(core_, sigs.ack_o,
false);
267 setBool(core_, sigs.err_o,
false);
268 setBool(core_, sigs.rty_o,
false);
269 setData<VECTORSIGSTORAGETYPE, VECTORSIG>(core_, sigs.dat_o, 0);
274 unsigned addressOffet = addr & (bytewidth - 1);
275 addr &= (~uint64_t(bytewidth - 1));
276 VECTORSIGSTORAGETYPE dataBuf = 0;
282 if (!sel2Length(
getSel(core_, sigs.sel_i), dataLength, addressOffet))
284 std::string(
"invalid sel_i: ") + std::to_string(
getSel(core_, sigs.sel_i)));
285 dataBuf = getData<VECTORSIGSTORAGETYPE, VECTORSIG>(core_, sigs.dat_i);
286 flipEndianness((
uint8_t *)&dataBuf);
287 exception = write(instrBus, localTime, addr + addressOffet,
288 ((
uint8_t *)&dataBuf) + addressOffet, dataLength);
299 if (!sel2Length(
getSel(core_, sigs.sel_i), dataLength, addressOffet))
301 std::string(
"invalid sel_i: ") + std::to_string(
getSel(core_, sigs.sel_i)));
302 exception = read(instrBus, localTime, addr + addressOffet,
303 ((
uint8_t *)&dataBuf) + addressOffet, dataLength);
304 flipEndianness((
uint8_t *)&dataBuf);
315 po_err = (exception == etiss::RETURNCODE::DBUS_READ_ERROR ||
316 exception == etiss::RETURNCODE::DBUS_WRITE_ERROR ||
317 exception == etiss::RETURNCODE::IBUS_READ_ERROR ||
318 exception == etiss::RETURNCODE::IBUS_WRITE_ERROR);
320 exception = etiss::RETURNCODE::NOERROR;
336 for (
unsigned i = 0; i < (bytewidth / 2); ++i)
338 std::swap(buf[i], buf[bytewidth - 1 - i]);
353 unsigned selectOffset = 0;
363 while ((sel & 1) == 0)
371 while ((sel & 1) == 1)
383 selectOffset = bytewidth -
length - selectOffset;
386 static bool output_addressOffset_warning =
false;
387 if ((selectOffset != addressOffset) && !output_addressOffset_warning)
390 std::string(
"Wishbone bus offset not valid! (0x") + std::to_string((
int)addressOffset) +
")");
391 output_addressOffset_warning =
true;
#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
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 + ...)
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