Jump to content

[Solved] How to implement sc_signal<int> with many writers?


unglaublich

Recommended Posts

SOLVED: Nevermind, I made some mistakes in calling the wrong methods for writing/reading from ports. Thanks for your attention anyway! 

I'm trying to implement this example of a memory and a cpu that are communicating. 

CPU <==> MEM

The modules use a single bidirectional data-line for reading/writing. 

I defined a signal in sc_main:

sc_signal<int,SC_MANY_WRITERS> s_memdata;

which I connect to the CPU and MEM module through their ports: 

sc_inout<int> p_memdata;

The CPU is writing to the s_memdata signal:

p_memdata.write(getrnddata());

As well as the memory:

p_data.write( m_data[ m_curAddr ] );

In the debugger I see that the m_curAddr is changing correctly. 

Yet, the VCD file shows that the signal "data" is not changing when the "address" is changed (as shown in the figure)

Screen Shot 2017-04-10 at 23.42.15.png

Actually, the "data" only changes when the cpu is writing to it, not when the memory is. (I was not able to show the function read/write signal because the enum didn't show in the VCD file). 

It seems to me that there is something going on with the two modules writing to the same channel. I've noticed sc_logic that introduces Z and X values, is this the appropriate way? 

edit: I've created a simple proof of principle with two writers that talk to a single sc_signal< bool, SC_MANY_WRITERS > which seems to work. So the problem is something different. 

Thanks for any help or tips. 

mem_tb.cpp

int sc_main(int argc, char* args[]){

  Memory * mem;
  CPU * cpu;

  mem = new Memory("main_memory");
  cpu = new CPU("cpu");

  /* sgn */
  sc_signal<Memory::Function,SC_MANY_WRITERS>
      s_memfunc;
  sc_signal<Memory::RETSignal>
      s_memsig;
  sc_signal<int>
      s_memaddr;
  sc_signal<int,SC_MANY_WRITERS>
      s_memdata;

  sc_clock clk;

  mem->p_addr(s_memaddr);
  mem->p_func(s_memfunc);
  mem->p_data(s_memdata);
  mem->p_sig(s_memsig);

  cpu->p_memdata(s_memdata);
  cpu->p_memaddr(s_memaddr);
  cpu->p_memsig(s_memsig);
  cpu->p_memfunc(s_memfunc);

  mem->clk( clk );
  cpu->clk( clk );

  std::cout << "Running, CTRL+C to exit..." << std::endl;

  sc_trace_file * trace = sc_create_vcd_trace_file("trace");

  sc_trace(trace, s_memaddr, "addr");
  sc_trace(trace, s_memdata, "data");
  sc_trace(trace, s_memfunc, "func");
  sc_trace(trace, s_memsig,  "sig");

  sc_start();

  sc_close_vcd_trace_file( trace );

  return 0;

}

cpu.h

#include <systemc.h>
#include "memory.h"
#include <boost/random.hpp>

SC_MODULE( CPU ) {

 public:
  sc_in<bool>               clk;
  sc_in<Memory::RETSignal>  p_memsig;
  sc_out<Memory::Function>  p_memfunc;
  sc_out<int>               p_memaddr;
  sc_inout<int>             p_memdata;

  SC_CTOR( CPU ) {

    SC_METHOD(exec);
    sensitive << clk.pos();
    dont_initialize();

    SC_METHOD(done);
    sensitive << p_memsig;
    dont_initialize();

    m_waitmem = false;

    rng.seed( time(NULL) );
    dist = new boost::random::uniform_int_distribution<>(0,1<<16);

  }

 private:
  boost::random::mt19937 rng;
  boost::random::uniform_int_distribution<> *dist;
  bool m_waitmem;
  int rand();

  Memory::Function getrndfunc();
  int getrndaddr();
  int getrnddata();
  void exec();
  void done();

};

cpu.cpp

 

Memory::Function CPU::getrndfunc()  {
  switch( rand() % 2 ) {
    case 0    : { return Memory::FUNC_READ;   }
    default   : { return Memory::FUNC_WRITE;  }   /* 1, and all other cases... */
  }
}

int CPU::getrndaddr() {
  return rand() % MEM_SIZE;
}

int CPU::getrnddata() {
  return rand();
}

int CPU::rand() {
  return (*dist)(rng);
}

void CPU::exec() {
  if(m_waitmem)
    return;

  int addr            = getrndaddr();
  Memory::Function f  = getrndfunc();

  p_memfunc.write(f);
  p_memaddr.write(addr);

  if(f==Memory::FUNC_WRITE)
    p_memdata.write(getrnddata());

}

void CPU::done() {
  if( p_memsig.read() == Memory::RSIG_NONE )
    return;

  m_waitmem = false;

  p_memfunc.write(Memory::FUNC_NONE);
}

memory.h

#define MEM_SIZE  512

SC_MODULE( Memory ) {

 public:
  enum Function {
    FUNC_NONE = 0, FUNC_READ = 1, FUNC_WRITE = 2
  };

  enum RETSignal {
    RSIG_NONE, RSIG_READ_FIN, RSIG_WRITE_FIN, RSIG_ERR
  };

  sc_in<bool>       clk;
  sc_in<Function>   p_func;

  sc_in<int>        p_addr;
  sc_inout<int>     p_data;
  sc_out<RETSignal> p_sig;

  SC_CTOR( Memory ){
    SC_METHOD(execute);
    sensitive << clk.neg();

    m_clkCnt = 0;
    m_curAddr = 0;
    m_curData = 0;
    m_curFunc = Memory::FUNC_NONE;

    m_data = new int[MEM_SIZE];

    m_writesCnt = 0;
    m_readsCnt = 0;
    m_errorsCnt = 0;
    m_errorCode = 0;

  }
  ~Memory();

 private:

  int       m_clkCnt;
  int       m_curAddr;
  int       m_curData;
  Function  m_curFunc;
  int*      m_data;
  int       m_errorCode;

  int       m_writesCnt;
  int       m_readsCnt;
  int       m_errorsCnt;

  RETSignal   read();
  RETSignal   write();
  void        execute();

};

memory.cpp

#include "memory.h"

Memory::~Memory() {
  delete[] m_data;
}

Memory::RETSignal Memory::read() {
  if( m_errorCode ) {
    m_errorsCnt++;
    return RSIG_ERR;
  }
  p_data.write( m_data[ m_curAddr ] );
  m_readsCnt++;
  return RSIG_READ_FIN;
}

Memory::RETSignal Memory::write() {
  if( m_errorCode ) {
    m_errorsCnt++;
    return RSIG_ERR;
  }
  m_data[ m_curAddr ] = m_curData;
  m_writesCnt++;
  return RSIG_WRITE_FIN;
}

void Memory::execute() {
  if( m_curFunc != FUNC_NONE ) {
    m_clkCnt++;

    if( m_clkCnt == 100 ) {
      RETSignal retSig = RSIG_ERR;

      switch(m_curFunc){
        case FUNC_READ    : { retSig = read();  break; }
        case FUNC_WRITE   : { retSig = write(); break; }
        default           : { /* */ }
      }

      p_sig.write( retSig );
      m_clkCnt = 0;
      m_curFunc = FUNC_NONE;
    }

    return;
  }

  if( p_func == FUNC_NONE )
    return;

  m_curFunc = p_func.read();
  m_curAddr = p_addr.read();
  m_curData = p_data.read();

  p_sig.write( RSIG_NONE );
}

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...