Skip to content

Commit 0ecb024

Browse files
committed
Update tlm
1 parent 24410ad commit 0ecb024

1 file changed

Lines changed: 47 additions & 210 deletions

File tree

content/posts/systemc_tlm.md

Lines changed: 47 additions & 210 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ ShowToc: true # Determines whether to display the Table of Contents (TOC) for
1111
TocOpen: true # Controls whether the TOC is expanded when the post is loaded.
1212
weight: 1 # The order in which the post appears in a list of posts. Lower numbers make the post appear earlier.
1313
---
14+
1415
Transaction-Level Modeling 2.0 (TLM-2.0) is a modeling methodology defined in IEEE 1666-2023.
1516
Instead of communicating through individual signals at every clock cycle, modules exchange complete **transactions** (read/write requests) using C++ function calls.
1617
This raises the abstraction level, dramatically increasing simulation speed and enabling early software development before RTL is available.
@@ -243,13 +244,52 @@ annotation and temporal decoupling
243244

244245
----
245246

246-
- **Non-blocking transport interface**
247-
- Each transaction has multiple timing points.
248-
- Uses **all paths**.
249-
- A transaction is finished through multiple calls or a single call.
250-
251-
----
252-
247+
## 7. Non-blocking Transport Interface
248+
- A transaction is break downed into multiple `phrases transition`.
249+
- Each phrases transition is associated with a `timing point`
250+
- Each `call/return` from the `non-blocking transport method` may `correspond to` a `phrase transition`
251+
- By restricting the number of timing points to two, it is possible to use the nb transport interface with the LT code style (not recommend)
252+
- It uses **all paths**, and interfaces `tlm_fw_nonblocking_transport_if` vs `tlm_bw_nonblocking_transport_if`
253+
> **Cơ chế truyền tham số của non-blocking transport interface tương tự blocking transport interface ở chỗ:
254+
truyền tham chiếu không const (non-const reference) tới transaction object truyền timing annotation
255+
Điểm khác biệt là: non-blocking transport method còn truyền thêm một phase để biểu thị trạng thái của transaction
256+
và trả về một giá trị enum để cho biết việc return từ function có đồng thời là một lần chuyển phase hay không**
257+
258+
### 7.1. Paths `nb_transport_fw` and `nb_transport_bw`
259+
260+
- `nb_transport` methods shall not call `wait`
261+
- several successive calls to `nb_transport_fw` from the same process could each initiate separate transactions without having to wait for the first transaction to complete
262+
- the `final timing point of a transaction` may be marked by a call to or a `return` from S`nb_transport` on either the forward path or the backward path.
263+
264+
### 7.1. Transaction Argument
265+
- 1 transaction = 1 object (while it is active)
266+
- That object moves back and forth between modules
267+
- Everyone touches the same object, not copies
268+
=> don't overwrite data too early or reuse object before transaction finishes
269+
270+
### 7.2. Phrase Argument
271+
- phase = control signal for "who can touch the transaction and when", including:
272+
- **BEGIN_REQ**: initiator controls
273+
- **END_REQ**: target takes over
274+
- **BEGIN_RESP**: target controls
275+
- **END_RESP**: initiator finishes
276+
277+
278+
### 7.3. <tlm_sync_enum> Return Value
279+
- **TLM_ACCEPTED**:
280+
- The callee must not modify the transaction object, phase, or time argument.
281+
- Indicates that the return path is not used.
282+
- The caller typically needs to wait/yield for a future response.
283+
- **TLM_UPDATED**:
284+
- Indicates that the return path is used.
285+
- The protocol state has advanced (phase transition occurred).
286+
- The caller must inspect updated arguments and react accordingly.
287+
- **TLM_COMPLETED**:The callee has completed the transaction (at this socket).
288+
- The transaction object and time may be modified.
289+
- The phase is undefined and should be ignored.
290+
- No further nb_transport calls are allowed for this transaction on this socket.
291+
- Completion does not guarantee success, need to check response status.
292+
---
253293
## 1.8 Examples
254294
## 1.8.1 Connection
255295
- **Module and socket:**
@@ -427,206 +467,3 @@ class InitiatorModule : public sc_module, public tlm::tlm_bw_transport_if<> {
427467
428468
429469
---
430-
431-
432-
## Creating Bus Master/Slave IP
433-
434-
### Master (Initiator) IP
435-
436-
```cpp
437-
SC_MODULE(MyMaster) {
438-
tlm::tlm_initiator_socket<> master_socket;
439-
440-
void do_transfer() {
441-
tlm::tlm_generic_payload trans;
442-
sc_core::sc_time delay = sc_core::SC_ZERO_TIME;
443-
unsigned char data[4];
444-
445-
trans.set_command(tlm::TLM_WRITE_COMMAND);
446-
trans.set_address(0x1000);
447-
trans.set_data_ptr(data);
448-
trans.set_data_length(4);
449-
trans.set_response_status(tlm::TLM_INCOMPLETE_RESPONSE);
450-
451-
master_socket->b_transport(trans, delay); // LT: blocking call
452-
}
453-
454-
SC_CTOR(MyMaster) {
455-
SC_THREAD(do_transfer);
456-
}
457-
};
458-
```
459-
460-
### Slave (Target) IP
461-
462-
```cpp
463-
SC_MODULE(MyTarget)
464-
: public tlm::tlm_fw_transport_if<>
465-
{
466-
tlm::tlm_target_socket<> slave_socket;
467-
unsigned char mem[4096];
468-
469-
void b_transport(tlm::tlm_generic_payload& trans,
470-
sc_core::sc_time& delay) override {
471-
sc_dt::uint64 addr = trans.get_address();
472-
unsigned char* ptr = trans.get_data_ptr();
473-
unsigned int len = trans.get_data_length();
474-
475-
if (trans.get_command() == tlm::TLM_WRITE_COMMAND)
476-
memcpy(mem + addr, ptr, len);
477-
else
478-
memcpy(ptr, mem + addr, len);
479-
480-
trans.set_response_status(tlm::TLM_OK_RESPONSE);
481-
delay += sc_core::sc_time(10, sc_core::SC_NS);
482-
}
483-
484-
SC_CTOR(MyTarget) {
485-
slave_socket.bind(*this);
486-
}
487-
// Other required interface methods omitted for brevity
488-
};
489-
```
490-
491-
---
492-
493-
## Example: SystemC Producer–Consumer with Event
494-
495-
The following example demonstrates `sc_module`, `SC_THREAD`, `sc_signal`, `sc_event`, and port binding in a single self-contained program.
496-
497-
```cpp
498-
#include <systemc.h>
499-
500-
SC_MODULE(Producer) {
501-
sc_out<int> data_out;
502-
sc_out<bool> valid_out;
503-
sc_event request_event; // external code can notify this
504-
505-
void produce() {
506-
int val = 0;
507-
while (true) {
508-
wait(10, SC_NS); // advance time
509-
data_out.write(val++);
510-
valid_out.write(true);
511-
wait(SC_ZERO_TIME); // delta cycle for the write to propagate
512-
valid_out.write(false);
513-
}
514-
}
515-
516-
SC_CTOR(Producer) {
517-
SC_THREAD(produce);
518-
}
519-
};
520-
521-
SC_MODULE(Consumer) {
522-
sc_in<int> data_in;
523-
sc_in<bool> valid_in;
524-
525-
void consume() {
526-
while (true) {
527-
wait(valid_in.posedge_event()); // wait for valid rising edge
528-
int v = data_in.read();
529-
std::cout << "@" << sc_time_stamp()
530-
<< " Received: " << v << "\n";
531-
}
532-
}
533-
534-
SC_CTOR(Consumer) {
535-
SC_THREAD(consume);
536-
}
537-
};
538-
539-
int sc_main(int, char*[]) {
540-
sc_signal<int> data;
541-
sc_signal<bool> valid;
542-
543-
Producer P("producer");
544-
Consumer C("consumer");
545-
546-
// Named port binding
547-
P.data_out(data);
548-
P.valid_out(valid);
549-
C.data_in(data);
550-
C.valid_in(valid);
551-
552-
sc_start(100, SC_NS);
553-
return 0;
554-
}
555-
```
556-
557-
---
558-
559-
## Example Exercise: 4-bit Up-Counter
560-
561-
The following implements a 4-bit up-counter with synchronous reset — a typical introductory SystemC design exercise.
562-
563-
```cpp
564-
#include <systemc.h>
565-
566-
// ── Module Definition ───────────────────────────────────────────────────────
567-
SC_MODULE(UpCounter4) {
568-
sc_in<bool> clk;
569-
sc_in<bool> rst; // synchronous active-high reset
570-
sc_out<sc_uint<4>> q; // 4-bit count output
571-
572-
sc_uint<4> count;
573-
574-
void do_count() {
575-
if (rst.read())
576-
count = 0;
577-
else
578-
count = count + 1;
579-
q.write(count);
580-
}
581-
582-
SC_CTOR(UpCounter4) : count(0) {
583-
SC_METHOD(do_count);
584-
sensitive << clk.pos(); // triggered on rising clock edge
585-
}
586-
};
587-
588-
// ── Testbench ───────────────────────────────────────────────────────────────
589-
SC_MODULE(Testbench) {
590-
sc_out<bool> clk;
591-
sc_out<bool> rst;
592-
sc_in<sc_uint<4>> q;
593-
594-
void run() {
595-
rst.write(1);
596-
clk.write(0);
597-
wait(20, SC_NS);
598-
599-
rst.write(0);
600-
for (int i = 0; i < 20; i++) {
601-
clk.write(1); wait(5, SC_NS);
602-
clk.write(0); wait(5, SC_NS);
603-
std::cout << "@" << sc_time_stamp()
604-
<< " count = " << q.read() << "\n";
605-
}
606-
sc_stop();
607-
}
608-
609-
SC_CTOR(Testbench) {
610-
SC_THREAD(run);
611-
}
612-
};
613-
614-
int sc_main(int, char*[]) {
615-
sc_signal<bool> clk_s, rst_s;
616-
sc_signal<sc_uint<4>> q_s;
617-
618-
UpCounter4 dut("dut");
619-
dut.clk(clk_s);
620-
dut.rst(rst_s);
621-
dut.q(q_s);
622-
623-
Testbench tb("tb");
624-
tb.clk(clk_s);
625-
tb.rst(rst_s);
626-
tb.q(q_s);
627-
628-
sc_start();
629-
return 0;
630-
}
631-
632-
```

0 commit comments

Comments
 (0)