Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <memory>
- #include <boost/format.hpp>
- #include <systemc.h>
- const sc_time clk(1, SC_NS);
- #define LOG(x) log(x)
- #define LOG_M(x) log_module(*this, x)
- #define LOG_C(m, x) log_module(m, x)
- void log(const std::string& s) {
- std::cout << boost::format("[%1%] %2%\n") % sc_time_stamp() % s;
- }
- void log(const boost::format& f) {
- log(boost::str(f));
- }
- template<class Message>
- void log_module(const sc_module& module, const Message& s) {
- log(boost::format("<%1%> %2%") % module.name() % s);
- }
- //////
- //////
- //////
- struct Flit {
- unsigned tag;
- uint64_t address;
- unsigned length;
- unsigned processing_time;
- sc_time earliest_sending;
- Flit()
- : tag(-1)
- , address{0}
- , length{0}
- , processing_time{0}
- , earliest_sending{SC_ZERO_TIME}
- {}
- Flit(unsigned tag, uint64_t address, unsigned length, unsigned processing_time)
- : tag{tag}
- , address{address}
- , length{length}
- , processing_time{processing_time}
- , earliest_sending{SC_ZERO_TIME}
- {}
- std::string to_str() const {
- return boost::str(boost::format("tag:%1%, addr:%2%, length:%3%, proc_time:%4%")
- % tag
- % address
- % length
- % processing_time
- );
- }
- inline friend std::ostream& operator<<(std::ostream& os, const Flit& flit) {
- os << flit.to_str();
- return os;
- }
- inline bool operator==(const Flit& flit) const {
- return tag == flit.tag;
- }
- };
- void sc_trace(sc_trace_file*& tf, const Flit& flit, const std::string& name) {
- sc_trace(tf, flit.tag, name + ".tag");
- sc_trace(tf, flit.address, name + ".address");
- sc_trace(tf, flit.length, name + ".length");
- sc_trace(tf, flit.processing_time, name + ".proc_time");
- }
- typedef sc_in<Flit> FlitInPort;
- typedef sc_out<Flit> FlitOutPort;
- typedef sc_signal<Flit> FlitSignal;
- typedef sc_in<unsigned> CreditReceivePort;
- typedef sc_out<unsigned> CreditReturnPort;
- typedef sc_buffer<unsigned> CreditSignal;
- //////
- //////
- //////
- class Source : public sc_module {
- SC_HAS_PROCESS(Source);
- public:
- FlitOutPort req_out;
- Source(const sc_module_name& module_name) {
- SC_THREAD(generate_request);
- }
- private:
- void generate_request() {
- send_flit(Flit(1, 0, 32, 10));
- wait(11 * clk);
- send_flit(Flit(2, 0, 32, 2));
- }
- void send_flit(const Flit& flit) {
- LOG_M(boost::format("Sending %1%") % flit);
- req_out.write(flit);
- }
- };
- class Buffer : public sc_module {
- SC_HAS_PROCESS(Buffer);
- public:
- FlitInPort req_in;
- FlitOutPort req_out;
- CreditReceivePort cr_rcv;
- Buffer(const sc_module_name& module_name) {
- SC_METHOD(receive);
- sensitive << req_in;
- dont_initialize();
- SC_METHOD(process_buffer);
- sensitive << process_buffer_event_;
- dont_initialize();
- SC_METHOD(receive_credits);
- sensitive << cr_rcv;
- dont_initialize();
- }
- private:
- std::vector<Flit> buffer_;
- sc_event process_buffer_event_;
- unsigned credits_ { 2 };
- void receive() {
- assert(req_in.event());
- auto& flit = req_in.read();
- LOG_M(boost::format("Received %1%") % flit.to_str());
- buffer_.push_back(flit);
- buffer_.back().earliest_sending = sc_time_stamp() + clk;
- process_buffer_event_.notify(clk);
- }
- void process_buffer() {
- if (buffer_.empty())
- return;
- if (credits_ == 0) {
- LOG_M("No credits!!!");
- return;
- }
- auto& flit = buffer_.front();
- LOG_M(boost::format("Sending %1%") % flit.to_str());
- assert(sc_time_stamp() >= flit.earliest_sending);
- req_out.write(flit);
- credits_--;
- buffer_.erase(begin(buffer_));
- if (!buffer_.empty())
- process_buffer_event_.notify(clk);
- }
- void receive_credits() {
- assert(cr_rcv.event());
- auto credits = cr_rcv.read();
- assert(credits > 0);
- credits_ += credits;
- LOG_M(boost::format("%1% credits received (total=%2%)") % credits % credits_);
- process_buffer_event_.notify(SC_ZERO_TIME);
- }
- };
- class Sink : public sc_module {
- SC_HAS_PROCESS(Sink);
- public:
- FlitInPort req_in;
- CreditReturnPort cr_ret;
- Sink(const sc_module_name& module_name) {
- SC_METHOD(receive);
- sensitive << req_in;
- dont_initialize();
- SC_METHOD(return_credit);
- sensitive << return_credit_event;
- dont_initialize();
- }
- private:
- sc_event_queue return_credit_event;
- void receive() {
- assert(req_in.event());
- auto& flit = req_in.read();
- LOG_M(boost::format("Received %1%)") % flit.to_str());
- return_credit_event.notify(flit.processing_time * clk);
- }
- void return_credit() {
- LOG_M("Returning one credit");
- cr_ret.write(1);
- }
- };
- int sc_main(int argc, char** argv) {
- Source source("source");
- Buffer buffer("buffer");
- Sink sink("sink");
- FlitSignal src_to_buf_signal;
- source.req_out(src_to_buf_signal);
- buffer.req_in(src_to_buf_signal);
- FlitSignal buf_to_sink_signal;
- buffer.req_out(buf_to_sink_signal);
- sink.req_in(buf_to_sink_signal);
- CreditSignal sink_to_buf_credit_signal;
- sink.cr_ret(sink_to_buf_credit_signal);
- buffer.cr_rcv(sink_to_buf_credit_signal);
- sc_start();
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement