scc 2026.07
SystemC components library
protocol_fsm.h
1/*
2 * Copyright 2020 -2022 Arteris IP
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.axi_util.cpp
15 */
16
17#pragma once
18
19#include "types.h"
20#include <array>
21#include <boost/mpl/list.hpp>
22#include <boost/statechart/custom_reaction.hpp>
23#include <boost/statechart/event.hpp>
24#include <boost/statechart/state.hpp>
25#include <boost/statechart/state_machine.hpp>
26#include <boost/statechart/transition.hpp>
27#include <functional>
28#include <iostream>
29
30namespace mpl = boost::mpl;
31namespace bsc = boost::statechart;
32
33namespace axi {
34namespace fsm {
35// Event Declarations
36struct WReq : bsc::event<WReq> {};
37struct BegPartReq : bsc::event<BegPartReq> {};
38struct EndPartReq : bsc::event<EndPartReq> {};
39struct BegReq : bsc::event<BegReq> {};
40struct EndReq : bsc::event<EndReq> {};
41struct BegPartResp : bsc::event<BegPartResp> {};
42struct EndPartResp : bsc::event<EndPartResp> {};
43struct BegResp : bsc::event<BegResp> {};
44struct EndResp : bsc::event<EndResp> {};
45struct EndRespNoAck : bsc::event<EndRespNoAck> {};
46struct AckRecv : bsc::event<AckRecv> {};
47// State forward Declarations
48struct Idle; // forward declaration
49struct ATrans;
50struct PartialRequest;
51struct WriteIdle;
52struct Request;
53struct WaitForResponse;
54struct PartialResponse;
55struct ReadIdle;
56struct Response;
57struct WaitAck;
61struct AxiProtocolFsm : bsc::state_machine<AxiProtocolFsm, Idle> {
62 void InvokeResponsePhaseBeg(const BegResp&) {
63 if(cb.at(axi::fsm::ResponsePhaseBeg))
64 cb.at(axi::fsm::ResponsePhaseBeg)();
65 };
66 void InvokeResponsePhaseBeg(const BegPartResp&) {
67 if(cb.at(axi::fsm::ResponsePhaseBeg))
68 cb.at(axi::fsm::ResponsePhaseBeg)();
69 };
70 void terminate() {
71 for(auto& f : cb)
72 f = nullptr;
73 bsc::state_machine<AxiProtocolFsm, Idle>::terminate();
74 }
75 axi::fsm::protocol_cb cb;
76};
77
78struct Idle : bsc::state<Idle, AxiProtocolFsm> { // @suppress("Class has a virtual method and non-virtual destructor")
79 Idle(my_context ctx)
80 : my_base(ctx) {}
81 ~Idle() {
82 if(context<AxiProtocolFsm>().cb.at(axi::fsm::RequestPhaseBeg))
83 context<AxiProtocolFsm>().cb.at(axi::fsm::RequestPhaseBeg)();
84 }
85 typedef mpl::list<bsc::transition<BegPartReq, PartialRequest>, bsc::transition<BegReq, Request>, bsc::transition<WReq, ATrans>>
86 reactions;
87};
88
89struct ATrans : bsc::state<ATrans, AxiProtocolFsm> { // @suppress("Class has a virtual method and non-virtual destructor")
90 ATrans(my_context ctx)
91 : my_base(ctx) {
92 if(context<AxiProtocolFsm>().cb.at(axi::fsm::WValidE))
93 context<AxiProtocolFsm>().cb.at(axi::fsm::WValidE)();
94 }
95 ~ATrans() {
96 if(context<AxiProtocolFsm>().cb.at(axi::fsm::WReadyE))
97 context<AxiProtocolFsm>().cb.at(axi::fsm::WReadyE)();
98 }
99 typedef mpl::list<bsc::transition<BegPartReq, PartialRequest>, bsc::transition<BegReq, Request>> reactions;
100};
101
102struct PartialRequest : bsc::state<PartialRequest, AxiProtocolFsm> { // @suppress("Class has a virtual method and non-virtual destructor")
103 PartialRequest(my_context ctx)
104 : my_base(ctx) {
105 if(context<AxiProtocolFsm>().cb.at(axi::fsm::BegPartReqE))
106 context<AxiProtocolFsm>().cb.at(axi::fsm::BegPartReqE)();
107 }
108 ~PartialRequest() {
109 if(context<AxiProtocolFsm>().cb.at(axi::fsm::EndPartReqE))
110 context<AxiProtocolFsm>().cb.at(axi::fsm::EndPartReqE)();
111 }
112 typedef bsc::transition<EndPartReq, WriteIdle> reactions;
113};
114
115struct WriteIdle : bsc::simple_state<WriteIdle, AxiProtocolFsm> { // @suppress("Class has a virtual method and non-virtual destructor")
116 typedef mpl::list<bsc::transition<BegPartReq, PartialRequest>, bsc::transition<BegReq, Request>> reactions;
117};
118
119struct Request : bsc::state<Request, AxiProtocolFsm> { // @suppress("Class has a virtual method and non-virtual destructor")
120 Request(my_context ctx)
121 : my_base(ctx) {
122 if(context<AxiProtocolFsm>().cb.at(axi::fsm::BegReqE))
123 context<AxiProtocolFsm>().cb.at(axi::fsm::BegReqE)();
124 }
125 ~Request() {
126 if(context<AxiProtocolFsm>().cb.at(axi::fsm::EndReqE))
127 context<AxiProtocolFsm>().cb.at(axi::fsm::EndReqE)();
128 }
129 typedef mpl::list<bsc::transition<EndReq, WaitForResponse>,
130 bsc::transition<BegResp, Response, AxiProtocolFsm, &AxiProtocolFsm::InvokeResponsePhaseBeg>,
131 bsc::transition<BegPartResp, PartialResponse, AxiProtocolFsm, &AxiProtocolFsm::InvokeResponsePhaseBeg>>
132 reactions;
133};
134
135struct WaitForResponse : bsc::state<WaitForResponse, AxiProtocolFsm> { // @suppress("Class has a virtual method and non-virtual destructor")
136 WaitForResponse(my_context ctx)
137 : my_base(ctx) {}
138 ~WaitForResponse() {
139 if(context<AxiProtocolFsm>().cb.at(axi::fsm::ResponsePhaseBeg))
140 context<AxiProtocolFsm>().cb.at(axi::fsm::ResponsePhaseBeg)();
141 }
142 typedef mpl::list<bsc::transition<BegPartResp, PartialResponse>, bsc::transition<BegResp, Response>> reactions;
143};
144
145struct PartialResponse : bsc::state<PartialResponse, AxiProtocolFsm> { // @suppress("Class has a virtual method and non-virtual destructor")
146 PartialResponse(my_context ctx)
147 : my_base(ctx) {
148 if(context<AxiProtocolFsm>().cb.at(axi::fsm::BegPartRespE))
149 context<AxiProtocolFsm>().cb.at(axi::fsm::BegPartRespE)();
150 }
151 ~PartialResponse() {
152 if(context<AxiProtocolFsm>().cb.at(axi::fsm::EndPartRespE))
153 context<AxiProtocolFsm>().cb.at(axi::fsm::EndPartRespE)();
154 }
155 typedef bsc::transition<EndPartResp, ReadIdle> reactions;
156};
157
158struct ReadIdle : bsc::simple_state<ReadIdle, AxiProtocolFsm> { // @suppress("Class has a virtual method and non-virtual destructor")
159 typedef mpl::list<bsc::transition<BegPartResp, PartialResponse>, bsc::transition<BegResp, Response>> reactions;
160};
161
162struct Response : bsc::state<Response, AxiProtocolFsm> { // @suppress("Class has a virtual method and non-virtual destructor")
163 Response(my_context ctx)
164 : my_base(ctx) {
165 if(context<AxiProtocolFsm>().cb.at(axi::fsm::BegRespE))
166 context<AxiProtocolFsm>().cb.at(axi::fsm::BegRespE)();
167 }
168 ~Response() {
169 if(context<AxiProtocolFsm>().cb.at(axi::fsm::EndRespE))
170 context<AxiProtocolFsm>().cb.at(axi::fsm::EndRespE)();
171 }
172 typedef mpl::list<bsc::transition<EndResp, Idle>, bsc::transition<EndRespNoAck, WaitAck>> reactions;
173};
174
175struct WaitAck : bsc::state<WaitAck, AxiProtocolFsm> { // @suppress("Class has a virtual method and non-virtual destructor")
176 WaitAck(my_context ctx)
177 : my_base(ctx) {}
178 ~WaitAck() {
179 if(context<AxiProtocolFsm>().cb.at(axi::fsm::Ack))
180 context<AxiProtocolFsm>().cb.at(axi::fsm::Ack)();
181 }
182 typedef bsc::transition<AckRecv, Idle> reactions;
183};
184} // namespace fsm
185} // namespace axi
TLM2.0 components modeling AHB.
special state to map AWREADY/WDATA of SNPS to AXI protocol
the idle state
the beat of a burst response
the phase between 2 read burst response beats
the request, either the last beat of a write or the address phase of a read
the write response or the last read response (beat)
waiting for ack in case of ACE access
the operation state where the target can do it's stuff
the phase between 2 burst beats, should keep the link locked