|
| 1 | +/* |
| 2 | + * TLM-2 to UMI bridge. |
| 3 | + * |
| 4 | + * Copyright (c) 2023 Zero ASIC |
| 5 | + * Written by Edgar E. Iglesias. |
| 6 | + * |
| 7 | + * SPDX-License-Identifier: MIT |
| 8 | + */ |
| 9 | + |
| 10 | +#ifndef TLM2UMI_BRIDGE_H__ |
| 11 | +#define TLM2UMI_BRIDGE_H__ |
| 12 | +#define SC_INCLUDE_DYNAMIC_PROCESSES |
| 13 | + |
| 14 | +#include "tlm-extensions/genattr.h" |
| 15 | +#include "tlm-bridges/umi.h" |
| 16 | +#include "utils/bitops.h" |
| 17 | + |
| 18 | +#undef D |
| 19 | +#define D(x) |
| 20 | + |
| 21 | +template <unsigned int DATA_WIDTH> |
| 22 | +class tlm2umi_bridge |
| 23 | +: public sc_core::sc_module |
| 24 | +{ |
| 25 | +public: |
| 26 | + tlm_utils::simple_target_socket<tlm2umi_bridge> socket; |
| 27 | + |
| 28 | + SC_HAS_PROCESS(tlm2umi_bridge); |
| 29 | + |
| 30 | + sc_in<bool> clk; |
| 31 | + sc_in<bool> rst; |
| 32 | + |
| 33 | + UMI_TX_PORT(req, DATA_WIDTH); |
| 34 | + UMI_RX_PORT(resp, DATA_WIDTH); |
| 35 | + |
| 36 | + tlm2umi_bridge(sc_core::sc_module_name name) : |
| 37 | + sc_module(name), |
| 38 | + socket("socket"), |
| 39 | + clk("clk"), |
| 40 | + rst("rst"), |
| 41 | + UMI_PORT_NAME(req), |
| 42 | + UMI_PORT_NAME(resp) |
| 43 | + { |
| 44 | + socket.register_b_transport(this, &tlm2umi_bridge::b_transport); |
| 45 | + } |
| 46 | + |
| 47 | +private: |
| 48 | + sc_mutex m_mutex; |
| 49 | + |
| 50 | + virtual void b_transport(tlm::tlm_generic_payload& trans, |
| 51 | + sc_time& delay) |
| 52 | + { |
| 53 | + unsigned int len = trans.get_data_length(); |
| 54 | + uint64_t addr = trans.get_address(); |
| 55 | + uint8_t *buf = trans.get_data_ptr(); |
| 56 | + genattr_extension *genattr; |
| 57 | + sc_bv<DATA_WIDTH> data = 0; |
| 58 | + unsigned int pos = 0; |
| 59 | + uint64_t srcaddr = 0; |
| 60 | + bool is_write = !trans.is_read(); |
| 61 | + |
| 62 | + trans.get_extension(genattr); |
| 63 | + if (genattr) { |
| 64 | + srcaddr = genattr->get_master_id(); |
| 65 | + } |
| 66 | + |
| 67 | + D(printf("TLM2UMI: we=%d addr=%lx len=%d\n", !trans.is_read(), addr, len)); |
| 68 | + // Since we're going to do waits in order to wiggle the |
| 69 | + // UMI signals, we need to eliminate the accumulated |
| 70 | + // TLM delay. |
| 71 | + wait(delay); |
| 72 | + delay = SC_ZERO_TIME; |
| 73 | + wait(clk.posedge_event()); |
| 74 | + resp_ready.write(1); |
| 75 | + |
| 76 | + m_mutex.lock(); |
| 77 | + do { |
| 78 | + unsigned int tlen = std::min(DATA_WIDTH/8, len - pos); |
| 79 | + umi_fields f; |
| 80 | + uint32_t cmd; |
| 81 | + |
| 82 | + if (is_write) { |
| 83 | + sc_bv<DATA_WIDTH> tmp; |
| 84 | + sc_buf2bv(buf+pos, tmp, tlen * 8); |
| 85 | + data = tmp; |
| 86 | + } |
| 87 | + |
| 88 | + f.size = 0; |
| 89 | + f.len = 0; |
| 90 | + switch (tlen) { |
| 91 | + case 2: f.size = 1; break; |
| 92 | + case 4: f.size = 2; break; |
| 93 | + case 8: f.size = 3; break; |
| 94 | + case 16: f.size = 4; break; |
| 95 | + case 32: f.size = 5; break; |
| 96 | + case 64: f.size = 6; break; |
| 97 | + case 128: f.size = 7; break; |
| 98 | + default: f.len = tlen - 1; |
| 99 | + }; |
| 100 | + |
| 101 | + f.opc = trans.is_read() ? UMI_REQ_READ : UMI_REQ_WRITE; |
| 102 | + f.eof = 1; |
| 103 | + cmd = f.pack(); |
| 104 | + |
| 105 | + req_cmd.write(cmd); |
| 106 | + req_srcaddr.write(srcaddr + pos); |
| 107 | + req_dstaddr.write(addr + pos); |
| 108 | + req_data.write(data); |
| 109 | + req_valid.write(1); |
| 110 | + resp_ready.write(1); |
| 111 | + |
| 112 | + do { |
| 113 | + wait(clk.posedge_event()); |
| 114 | + } while(!req_ready.read()); |
| 115 | + req_valid.write(0); |
| 116 | + |
| 117 | + do { |
| 118 | + wait(clk.posedge_event()); |
| 119 | + } while(!resp_valid.read()); |
| 120 | + |
| 121 | + if (!is_write) { |
| 122 | + sc_bv2buf(buf + pos, resp_data.read(), tlen * 8); |
| 123 | + } |
| 124 | + pos += tlen; |
| 125 | + } while (pos < len); |
| 126 | + resp_ready.write(0); |
| 127 | + wait(clk.posedge_event()); |
| 128 | + |
| 129 | + trans.set_response_status(tlm::TLM_OK_RESPONSE); |
| 130 | + m_mutex.unlock(); |
| 131 | + } |
| 132 | +}; |
| 133 | +#undef D |
| 134 | +#endif |
0 commit comments