void simple_bus_master_blocking::main_action() { const unsigned int mylength = 0x04; // storage capacity/burst length in words int mydata[mylength]; unsigned int i; simple_bus_status status; while (true) { wait(); // ... for the next rising clock edge status = bus_port->burst_read(m_unique_priority, mydata, m_address, mylength, m_lock); if (status == SIMPLE_BUS_ERROR) sb_fprintf(stdout, "%g %s : blocking-read failed at address %x\n", sc_time_stamp().to_double(), name(), m_address); for (i = 0; i < mylength; ++i) { mydata[i] += i; wait(); } status = bus_port->burst_write(m_unique_priority, mydata, m_address, mylength, m_lock); if (status == SIMPLE_BUS_ERROR) sb_fprintf(stdout, "%g %s : blocking-write failed at address %x\n", sc_time_stamp().to_double(), name(), m_address); wait(m_timeout, SC_NS); } }
simple_bus_status simple_bus::burst_write(unsigned int unique_priority , int *data , unsigned int start_address , unsigned int length , bool lock) { if (m_verbose) sb_fprintf(stdout, "%g %s : burst_write(%d) @ %x\n", sc_time_stamp().to_double(), name(), unique_priority, start_address); simple_bus_request *request = get_request(unique_priority); request->do_write = true; // we are writing request->address = start_address; request->end_address = start_address + (length-1)*4; request->data = data; if (lock) request->lock = (request->lock == SIMPLE_BUS_LOCK_SET) ? SIMPLE_BUS_LOCK_GRANTED : SIMPLE_BUS_LOCK_SET; request->status = SIMPLE_BUS_REQUEST; wait(request->transfer_done); wait(clock->posedge_event()); return request->status; }
/* First try to use the eqawarn program from portage. If that fails, fall * back to writing to /dev/tty. While this might annoy some people, using * stderr will break tests that try to validate output #261957. */ void sb_eqawarn(const char *format, ...) { va_list args; FILE *fp; sighandler_t oldsig; bool is_pipe; /* If popen() fails, then writes to it will trigger SIGPIPE */ oldsig = signal(SIGPIPE, SIG_IGN); fp = sb_unwrapped_popen("xargs eqawarn 2>/dev/null", "we"); is_pipe = true; if (!fp) { do_tty: is_pipe = false; fp = fopen("/dev/tty", "ae"); if (!fp) fp = stderr; } sb_fprintf(fp, "QA Notice: "); va_start(args, format); sb_vfprintf(fp, format, args); va_end(args); if (is_pipe) { int status = pclose(fp); if (WEXITSTATUS(status)) goto do_tty; } signal(SIGPIPE, oldsig); }
void simple_bus::write(unsigned int unique_priority , int *data , unsigned int address , bool lock) { if (m_verbose) sb_fprintf(stdout, "%g %s : write(%d) @ %x\n", sc_time_stamp().to_double(), name(), unique_priority, address); simple_bus_request *request = get_request(unique_priority); // abort when the request is still not finished sc_assert((request->status == SIMPLE_BUS_OK) || (request->status == SIMPLE_BUS_ERROR)); request->do_write = true; // we are writing request->address = address; request->end_address = address; request->data = data; if (lock) request->lock = (request->lock == SIMPLE_BUS_LOCK_SET) ? SIMPLE_BUS_LOCK_GRANTED : SIMPLE_BUS_LOCK_SET; request->status = SIMPLE_BUS_REQUEST; }
void simple_bus::end_of_elaboration() { // perform a static check for overlapping memory areas of the slaves bool no_overlap; for (int i = 1; i < slave_port.size(); ++i) { simple_bus_slave_if *slave1 = slave_port[i]; for (int j = 0; j < i; ++j) { simple_bus_slave_if *slave2 = slave_port[j]; no_overlap = ( slave1->end_address() < slave2->start_address() ) || ( slave1->start_address() > slave2->end_address() ); if ( !no_overlap ) { sb_fprintf(stdout,"Error: overlapping address spaces of 2 slaves : \n"); sb_fprintf(stdout,"slave %i : %0X..%0X\n",i,slave1->start_address(),slave1->end_address()); sb_fprintf(stdout,"slave %i : %0X..%0X\n",j,slave2->start_address(),slave2->end_address()); exit(0); } } } }
bool simple_bus::direct_write(int *data, unsigned int address) { if (address%4 != 0 ) {// address not word alligned sb_fprintf(stdout, " BUS ERROR --> address %04X not word alligned\n",address); return false; } simple_bus_slave_if *slave = get_slave(address); if (!slave) return false; return slave->direct_write(data, address); }
void simple_bus_master_non_blocking::main_action() { int mydata; int cnt = 0; unsigned int addr = m_start_address; wait(); // ... for the next rising clock edge while (true) { bus_port->read(m_unique_priority, &mydata, addr, m_lock); while ((bus_port->get_status(m_unique_priority) != SIMPLE_BUS_OK) && (bus_port->get_status(m_unique_priority) != SIMPLE_BUS_ERROR)) wait(); if (bus_port->get_status(m_unique_priority) == SIMPLE_BUS_ERROR) sb_fprintf(stdout, "%g %s : ERROR cannot read from %x\n", sc_time_stamp().to_double(), name(), addr); mydata += cnt; cnt++; bus_port->write(m_unique_priority, &mydata, addr, m_lock); while ((bus_port->get_status(m_unique_priority) != SIMPLE_BUS_OK) && (bus_port->get_status(m_unique_priority) != SIMPLE_BUS_ERROR)) wait(); if (bus_port->get_status(m_unique_priority) == SIMPLE_BUS_ERROR) sb_fprintf(stdout, "%g %s : ERROR cannot write to %x\n", sc_time_stamp().to_double(), name(), addr); wait(m_timeout, SC_NS); wait(); // ... for the next rising clock edge addr+=4; // next word (byte addressing) if (addr > (m_start_address+0x80)) { addr = m_start_address; cnt = 0; } } }
void simple_bus_master_direct::main_action() { int mydata[4]; while (true) { bus_port->direct_read(&mydata[0], m_address); bus_port->direct_read(&mydata[1], m_address+4); bus_port->direct_read(&mydata[2], m_address+8); bus_port->direct_read(&mydata[3], m_address+12); if (m_verbose) sb_fprintf(stdout, "%g %s : mem[%x:%x] = (%x, %x, %x, %x)\n", sc_simulation_time(), name(), m_address, m_address+15, mydata[0], mydata[1], mydata[2], mydata[3]); wait(m_timeout, SC_NS); } }
void simple_bus::main_action() { // m_current_request is cleared after the slave is done with a // single data transfer. Burst requests require the arbiter to // select the request again. if (!m_current_request) m_current_request = get_next_request(); else // monitor slave wait states if (m_verbose) sb_fprintf(stdout, "%g SLV [%d]\n", sc_time_stamp().to_double(), m_current_request->address); if (m_current_request) handle_request(); if (!m_current_request) clear_locks(); }
simple_bus_request * simple_bus::get_next_request() { // the slave is done with its action, m_current_request is // empty, so go over the bag of request-forms and compose // a set of likely requests. Pass it to the arbiter for the // final selection simple_bus_request_vec Q; for (int i = 0; i < m_requests.size(); ++i) { simple_bus_request *request = m_requests[i]; if ((request->status == SIMPLE_BUS_REQUEST) || (request->status == SIMPLE_BUS_WAIT)) { if (m_verbose) sb_fprintf(stdout, "%g %s : request (%d) [%s]\n", sc_time_stamp().to_double(), name(), request->priority, simple_bus_status_str[request->status]); Q.push_back(request); } } if (Q.size() > 0) return arbiter_port->arbitrate(Q); return (simple_bus_request *)0; }
void simple_bus::handle_request() { if (m_verbose) sb_fprintf(stdout, "%g %s Handle Slave(%d)\n", sc_time_stamp().to_double(), name(), m_current_request->priority); m_current_request->status = SIMPLE_BUS_WAIT; simple_bus_slave_if *slave = get_slave(m_current_request->address); if ((m_current_request->address)%4 != 0 ) // address not word alligned { sb_fprintf(stdout, " BUS ERROR --> address %04X not word alligned\n",m_current_request->address); m_current_request->status = SIMPLE_BUS_ERROR; m_current_request = (simple_bus_request *)0; return; } if (!slave) { sb_fprintf(stdout, " BUS ERROR --> no slave for address %04X \n",m_current_request->address); m_current_request->status = SIMPLE_BUS_ERROR; m_current_request = (simple_bus_request *)0; return; } simple_bus_status slave_status = SIMPLE_BUS_OK; if (m_current_request->do_write) slave_status = slave->write(m_current_request->data, m_current_request->address); else slave_status = slave->read(m_current_request->data, m_current_request->address); if (m_verbose) sb_fprintf(stdout, " --> status=(%s)\n", simple_bus_status_str[slave_status]); switch (slave_status) { case SIMPLE_BUS_ERROR: m_current_request->status = SIMPLE_BUS_ERROR; m_current_request->transfer_done.notify(); m_current_request = (simple_bus_request *)0; break; case SIMPLE_BUS_OK: m_current_request->address+=4; //next word (byte addressing) m_current_request->data++; if (m_current_request->address > m_current_request->end_address) { // burst-transfer (or single transfer) completed m_current_request->status = SIMPLE_BUS_OK; m_current_request->transfer_done.notify(); m_current_request = (simple_bus_request *)0; } else { // more data to transfer, but the (atomic) slave transfer is done m_current_request = (simple_bus_request *)0; } break; case SIMPLE_BUS_WAIT: // the slave is still processing: no clearance of the current request break; default: break; } }