scc 2025.09
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) f=nullptr;
72 bsc::state_machine<AxiProtocolFsm, Idle>::terminate();
73 }
74 axi::fsm::protocol_cb cb;
75};
76
77struct Idle : bsc::state<Idle, AxiProtocolFsm> { // @suppress("Class has a virtual method and non-virtual destructor")
78 Idle(my_context ctx)
79 : my_base(ctx) {}
80 ~Idle() {
81 if(context<AxiProtocolFsm>().cb.at(axi::fsm::RequestPhaseBeg))
82 context<AxiProtocolFsm>().cb.at(axi::fsm::RequestPhaseBeg)();
83 }
84 typedef mpl::list<bsc::transition<BegPartReq, PartialRequest>, bsc::transition<BegReq, Request>,
85 bsc::transition<WReq, ATrans>>
86 reactions;
87};
88
89struct ATrans
90: bsc::state<ATrans, AxiProtocolFsm> { // @suppress("Class has a virtual method and non-virtual destructor")
91 ATrans(my_context ctx)
92 : my_base(ctx) {
93 if(context<AxiProtocolFsm>().cb.at(axi::fsm::WValidE))
94 context<AxiProtocolFsm>().cb.at(axi::fsm::WValidE)();
95 }
96 ~ATrans() {
97 if(context<AxiProtocolFsm>().cb.at(axi::fsm::WReadyE))
98 context<AxiProtocolFsm>().cb.at(axi::fsm::WReadyE)();
99 }
100 typedef mpl::list<bsc::transition<BegPartReq, PartialRequest>, bsc::transition<BegReq, Request>> reactions;
101};
102
103struct PartialRequest
104: bsc::state<PartialRequest, AxiProtocolFsm> { // @suppress("Class has a virtual method and non-virtual destructor")
105 PartialRequest(my_context ctx)
106 : my_base(ctx) {
107 if(context<AxiProtocolFsm>().cb.at(axi::fsm::BegPartReqE))
108 context<AxiProtocolFsm>().cb.at(axi::fsm::BegPartReqE)();
109 }
110 ~PartialRequest() {
111 if(context<AxiProtocolFsm>().cb.at(axi::fsm::EndPartReqE))
112 context<AxiProtocolFsm>().cb.at(axi::fsm::EndPartReqE)();
113 }
114 typedef bsc::transition<EndPartReq, WriteIdle> reactions;
115};
116
118: bsc::simple_state<WriteIdle, AxiProtocolFsm> { // @suppress("Class has a virtual method and non-virtual destructor")
119 typedef mpl::list<bsc::transition<BegPartReq, PartialRequest>, bsc::transition<BegReq, Request>> reactions;
120};
121
122struct Request
123: bsc::state<Request, AxiProtocolFsm> { // @suppress("Class has a virtual method and non-virtual destructor")
124 Request(my_context ctx)
125 : my_base(ctx) {
126 if(context<AxiProtocolFsm>().cb.at(axi::fsm::BegReqE))
127 context<AxiProtocolFsm>().cb.at(axi::fsm::BegReqE)();
128 }
129 ~Request() {
130 if(context<AxiProtocolFsm>().cb.at(axi::fsm::EndReqE))
131 context<AxiProtocolFsm>().cb.at(axi::fsm::EndReqE)();
132 }
133 typedef mpl::list<
134 bsc::transition<EndReq, WaitForResponse>,
135 bsc::transition<BegResp, Response, AxiProtocolFsm, &AxiProtocolFsm::InvokeResponsePhaseBeg>,
136 bsc::transition<BegPartResp, PartialResponse, AxiProtocolFsm, &AxiProtocolFsm::InvokeResponsePhaseBeg>>
137 reactions;
138};
139
140struct WaitForResponse
141: bsc::state<WaitForResponse, AxiProtocolFsm> { // @suppress("Class has a virtual method and non-virtual destructor")
142 WaitForResponse(my_context ctx)
143 : my_base(ctx) {}
144 ~WaitForResponse() {
145 if(context<AxiProtocolFsm>().cb.at(axi::fsm::ResponsePhaseBeg))
146 context<AxiProtocolFsm>().cb.at(axi::fsm::ResponsePhaseBeg)();
147 }
148 typedef mpl::list<bsc::transition<BegPartResp, PartialResponse>, bsc::transition<BegResp, Response>> reactions;
149};
150
151struct PartialResponse
152: bsc::state<PartialResponse, AxiProtocolFsm> { // @suppress("Class has a virtual method and non-virtual destructor")
153 PartialResponse(my_context ctx)
154 : my_base(ctx) {
155 if(context<AxiProtocolFsm>().cb.at(axi::fsm::BegPartRespE))
156 context<AxiProtocolFsm>().cb.at(axi::fsm::BegPartRespE)();
157 }
158 ~PartialResponse() {
159 if(context<AxiProtocolFsm>().cb.at(axi::fsm::EndPartRespE))
160 context<AxiProtocolFsm>().cb.at(axi::fsm::EndPartRespE)();
161 }
162 typedef bsc::transition<EndPartResp, ReadIdle> reactions;
163};
164
166: bsc::simple_state<ReadIdle, AxiProtocolFsm> { // @suppress("Class has a virtual method and non-virtual destructor")
167 typedef mpl::list<bsc::transition<BegPartResp, PartialResponse>, bsc::transition<BegResp, Response>> reactions;
168};
169
170struct Response
171: bsc::state<Response, AxiProtocolFsm> { // @suppress("Class has a virtual method and non-virtual destructor")
172 Response(my_context ctx)
173 : my_base(ctx) {
174 if(context<AxiProtocolFsm>().cb.at(axi::fsm::BegRespE))
175 context<AxiProtocolFsm>().cb.at(axi::fsm::BegRespE)();
176 }
177 ~Response() {
178 if(context<AxiProtocolFsm>().cb.at(axi::fsm::EndRespE))
179 context<AxiProtocolFsm>().cb.at(axi::fsm::EndRespE)();
180 }
181 typedef mpl::list<bsc::transition<EndResp, Idle>, bsc::transition<EndRespNoAck, WaitAck>> reactions;
182};
183
184struct WaitAck
185: bsc::state<WaitAck, AxiProtocolFsm> { // @suppress("Class has a virtual method and non-virtual destructor")
186 WaitAck(my_context ctx)
187 : my_base(ctx) {}
188 ~WaitAck() {
189 if(context<AxiProtocolFsm>().cb.at(axi::fsm::Ack))
190 context<AxiProtocolFsm>().cb.at(axi::fsm::Ack)();
191 }
192 typedef bsc::transition<AckRecv, Idle> reactions;
193};
194} // namespace fsm
195} // 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