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);
    }
}
Beispiel #2
0
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);
}
Beispiel #4
0
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;
}
Beispiel #5
0
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);
            }
        }
    }
}
Beispiel #6
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);
    }
}
Beispiel #9
0
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();
}
Beispiel #10
0
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;
}
Beispiel #11
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;
    }
}