SystemC入门学习-第8章 测试平台的编写

        之前的章节,一直把重点放在用SystemC来描述硬件电路上,即如何编写SystemC 的RTL。本章的注意力集中在验证和编写测试平台上。

重点包括:

  • 如何生成时钟信号和激励波形
  • 如何编写有响应能力的测试平台
  • 如何记录仿真结果

8.1 编写测试平台

        测试平台是检测并验证被测试设计正确定的模型。SystemC 不但可以描述设计,也可以编写测试平台。测试平台可以实现如下三个主要目标:

  • 为仿真生成激励(波形);
  • 将激励施加到被测设计中并记录输出响应;
  • 将输出响应与期望的输出值进行比较;

        测试平台可以用多种不同的方式进行编写。如下是其中一种方式:

        有三个主要模块,激励生成模块(stimulus.h, stimulus.cpp),  输出的检测和比较模块(monitor.h和monitor.cpp), 被测设计模块(dut.h和dut.cpp)。主程序main.cpp链接了这三个不同模块并将它们互相连接起来,构成一个测试平台。

        另一种方式是:

        将激励的生成和对输出的检测功能都嵌入到主程序中;或使用一个模块生成激励,而将检测比较和结果都嵌入到主程序中。

        具体的方式完全根据用户、风格、测试和设计的复杂程度来决定。在规模比较大的设计中,上面第一种分成三个模块的风格是非常有用的,因为这些模块可能比较大。

        下面的文件main.cpp展示了一个测试平台的结构

//这里包含其它文件(#include 编译指令)int sc_main(int argc, char* argv[])
{//这里声明sc_signal, 用于连接所引用的不同实例模型//声明时钟 sc_clock//被测设计、激励模块和监测模块的实例引用//创建记录仿真波形的(trace)文件,并进行监测//仿真的开始和控制
}

        必须为每一个准备测试的、使用SystemC描述的设计编写函数sc_main()。函数sc_main()是一个主程序,该主程序不但实例引用了被测设计模块,还引用了其它模块,他们在一起被编译和链接,最后生成一个可执行文件。当运行该可执行文件时,该主程序就会开始运行仿真。

  • 在函数sc_main()中,模块的实例引用可通过两种途径来实现:1)将模块声明为对象;2)使用new操作符。
  • 使用sc_signal和sc_clock声明的信号可用于连接实例的端口。可采用两种不同方式进行端口连接1)按端口名称进行连接;2)按端口位置进行连接。
sc_signal <bool> clk, resetn;
sc_signal <sc_uint<4> > din;
sc_signal <sc_lv<4> > dout;tristate_reg tr1("tristate_reg_tr1"); //将模块声明为对象//通过端口名进行信号连接
tr1.clock(clk);  
tr1.reset(resetn);
tr1.data_in(din);
tr1.data_out(dout);tristate_reg tr2 = new tristate_reg ("tristate_reg_tr1"); //通过new操作符实现模块实例的引用
//通过端口位置进行信号连接
tr2 << clk << resetn << din << dout;

8.2 仿真控制

SystemC提供一下结构来协助仿真。

  • sc_clock  生成时钟信号
  • sc_trace 将仿真波形信息记录到一个指定格式的文件中
  • sc_start 启动并运行仿真到指定时间
  • sc_stop 停止仿真
  • sc_time_stamp 获取当前带时间单位的仿真时间
  • sc_simulation_time 获取当前不带时间单位的仿真时间
  • sc_cycle, sc_initialize 用于执行周期循环级仿真
  • sc_time 指定之间值 

sc_clock

        如下示例,时钟波形rclk的开关周期是10ns, 默认占空比是50%,默认初始值为真(1);

        时钟波形mclk周期是10ns, 占空比是20%, 第一个跳变沿出现在5ns之后,且在第一个跳变沿之后值为假(0);

        第一个参数是时钟名称,必须指定时钟名称,如clka, 如果没有指定周期,默认为1个默认时间单位。在SystemC中默认时间单位是1ns。所以clka周期是1ns,占空比50%,第一个跳变沿发生在0时刻,且在第一个跳变沿后的初始值为真。

sc_clock rclk("rclk", 10, SC_NS);
sc_clock mclk("mclk", 10, SC_NS, 0.2, 5, SC_NS, false);
sc_clock clka("clka");

sc_trace

        SystemC可以通过三种不同格式来保存仿真结果,它们是是:

1)VCD(值变记录)格式;调用sc_create_vcd_trace_file()来打开文件,会自动加扩展名.vcd。

2)WIF(波形交换)格式; 调用sc_create_wif_trace_file()来打开文件,会自动加扩展名.awif。

3)ISDB(统一信号数据库)格式。调用sc_create_isdb_trace_file()来打开文件,会自动加扩展名.isdb。

        调用sc_trace()可以指定一些信号,并将它们的值保存在仿真波形记录文件中。通常最好将字符串参数名和信号名保持一致。

sc_trace(tfile, signal_name, "signal_name");

        在退出测试平台sc_main()函数之前,必须选择相应的函数来关闭仿真波形记录文件。

sc_close_vcd_trace_file(tfile);

        必须先打开仿真波形记录文件,然后在创建需要记录的信号后才能调用sc_trace()函数将波形记录到文件中。

        VCD文件中的时间单位可以调用sc_set_vcd_time_uint()方法来设置。如下示例,该方法的参变量是一个时间单位,该时间单位是以10为底的指数。所以参变量-6对应的时间单位是μs。参变量默认值是-9(ns)。

sc_trace_file *trace_file = sc_create_vcd_trace_file("ahb_trans.vcd");
((vcd_trace_file *)trace_file)->sc_set_vcd_time_uint(-6);

        可以将以∆周期(delta cycle)为节拍的仿真波形存入VCD文件中,波形观测器需要VCD文件才能显示仿真波形。使用函数delta_cycles()可以使能或禁止对以∆周期为节拍的仿真波形进行记录。参变量为真,则开始记录波形,为假,则停止记录仿真波形。

trace_file->delta_cycles(true);
...
trace_file->delta_cycles(false);
...
trace_file->delta_cycles(true);
...

sc_start/sc_stop

        sc_start()方法告诉仿真内核启动仿真。该方法的调用必须出现在实例引用所有模块之后,也必须出现在调用所有仿真波形记录函数之后。

        下面是调用的方法示例,在仿真过程中可以多次调用函数sc_start(), 若需要重新启动仿真,则只需要启动仿真的执行文件即可。

sc_start(100, SC_MS);  //启动仿真并运行100nssc_start(-1);  //启动仿真并一直运行

        任何进程都可以调用sc_stop()方法来停止仿真,调用格式如下,不需要任何参数,在调用sc_stop()之后,不能在调用sc_start()方法。

sc_stop();  

sc_time_stamp/sc_simultion_time

        sc_time_stamp()方法用于返回当前的仿真时间(带有时间单位)。例如:

cout << "Current time is "<< sc_time_stamp() <<endl;

        将打印如下信息:

Current time is 25ns

        sc_simultion_time在最近的SystemC版本已经被IEEE_Std_1666/deprecated,下面是之前老版本的定义。

        sc_simulation_time()方法根据默认的时间单位,以double(不带时间单位的双精度)类型的整数值格式返回当前仿真时间,例如:

double current_time = sc_simulation_time();
cout << "Time now is %f" <<current_time <<endl;

        将打印如下信息:

Tiem now is 96

sc_cycle/sc_initialize

        这两个方法用于执行按周期节拍的仿真。例如想每过10个时间单位就计算一次设计的输出结果,就须使用周期节拍的仿真。这种情况下,不要使用方法sc_start(),而要使用sc_initialize()和sc_cycle()这两个方法。

        sc_initialize()方法用于对仿真内核进行初始化。sc_cycle()方法执行所有准备运行的进程,直到不再需要有进程执行,但这将需要许多个∆周期节拍。在仿真时间再次前进指定的时间长度之前,sc_cycle()方法会将一些必要信号的仿真信息记录下来。

        下面语句将仿真所有进程,并将仿真时间向前推进10μs。

sc_cycle(10, SC_US);  

sc_time

        sc_time用于声明由参量表示的时间值,如10ns, 20ps等。由sc_time声明的变量可以在需要指定时间值的地方使用,如sc_clock()和sc_start()中。

sc_time t1(100, SC_NS);
sc_time t2(20, SC_PS); //指定t2的值为20ps//这两种方式等价
sc_start(t1);
sc_start(100, SC_NS);sc_cycle(t2);sc_time period(10, SC_NS);
sc_time start_time(2, SC_NS);
sc_clock fclk("fclk", period, 0.2, start_time, true);

        时间单位有如下几种: SC_FS, SC_PS, SC_NS, SC_US, SC_MS, SC_SEC。

        默认的时间分辨率是1ps。可以通过sc_set_time_resolution()来修改。例如:

sc_set_time_resolution(100, SC_PS);

        指定时间分辨率只能是10的幂,并且经常是在主程序sc_main()的最开始处指定一次时间分辨率。

        打印不同时间单位的转换函数有:

sc_time curr_time = sc_time_stamp();cout <<"As double: " << curr_time.to_double() <<endl;
cout <<"In seconds: " << curr_time.to_seconds() <<endl;
cout <<"In default time units: " << curr_time.to_default_time_units() <<endl;
cout <<"In string form:" << curr_time.to_string() <<endl;cout <<"sc_time_stamp():" << sc_time_stamp() <<endl;

        打印如下:

As double: 100000
In seconds: 1e-07
In default time units: 100
In string form:100 ns
sc_time_stamp():100 ns

8.3 波形

        普通波形,如时钟波形,可以通过调用sc_clock声明语句来生成。实际上,也可以通过在模块中使用SC_METHOD类型进程来生成任意类型的波形。

示例1,建模任意波形

SC_THREAD类型的进程prc_wave何时执行呢?在初始化时刻。所有进程都在初始化时刻(即在仿真开始之前的瞬间)执行一次。根据进程的执行,输出端口sig_out被赋值为0。接下来等待语句使得进程prc_wave被挂起并等待5ns。在5ns之后,sig_out被赋值1,然后该进程被挂起2ns,后面过程类似。

#include "systemc.h"SC_MODULE(wave){sc_out <bool> sig_out;void prc_wave();SC_CTOR(wave){SC_THREAD(prc_wave);}};void wave::prc_wave(){sig_out = 0;wait(5, SC_NS);sig_out = 1;wait(2,SC_NS);sig_out = 0;wait(5, SC_NS);sig_out = 1;wait(8,SC_NS);sig_out = 0;
}

示例2,建模复杂的重复波形

如果想每100ns重复一次上面的波形,那怎么办呢?可以在SC_THREAD类型进程使用一个永不停止的while循环语句来实现。如下:

void wave::prc_wave(){sig_out = 0;wait(5, SC_NS);sig_out = 1;wait(2,SC_NS);sig_out = 0;wait(5, SC_NS);sig_out = 1;wait(8,SC_NS);sig_out = 0;wait(80, SC_NS);
}

示例3,自定义时钟发生器

#include "systemc.h"const int START_VALUE = 0;
const int INITIAL_DELAY = 5;
const int FIRST_DELAY = 2;
const int SECOND_DELAY = 3;SC_MODULE(myclock){sc_out <bool> clk_out;void prc_myclock();SC_CTOR(myclock){SC_THREAD(prc_myclock);}};void myclock::prc_myclock(){clk_out = START_VALUE;wait(INITIAL_DELAY, SC_NS);while(1){clk_out = !(clk_out);wait(FIRST_DELAY, SC_NS);clk_out = !clk_out;wait(SECOND_DELAY, SC_NS);}
}

示例4,完整测试平台搭建的生成一个衍生时钟

pulse.h文件 

#include "systemc.h"#define DELAY 2, SC_NS
#define ON_DURATION 1, SC_NSSC_MODULE(pulse){sc_in <bool> clk;sc_out <bool> pulse_out;void prc_pulse();SC_CTOR(pulse){SC_THREAD(prc_pulse);sensitive_pos << clk;}};void pulse::prc_pulse(){pulse_out = 0;while(true){wait();wait(DELAY);pulse_out = 1;wait(ON_DURATION);pulse_out = 0;}
}

        SC_THREAD进程可以带敏感列表,也可以不带敏感列表;prc_pulse中while的第一个wait()等待语句 是等待敏感列表中的某个信号发生变化。

pulse_main.cpp

#include "pulse.h"int sc_main(int argc, char * argv[]){sc_signal <bool> pout;sc_trace_file *tf;sc_clock clock("master_clk", 5, SC_NS);//pulse模块的实例引用pulse p1("pulse_p1");p1.clk(clock);p1.pulse_out(pout);//创建仿真波形记录文件pulse.vcd, 并设置需要记录波形的信号tf = sc_create_vcd_trace_file("pulse");sc_trace(tf, clock, "clock");sc_trace(tf, pout, "pulse_out");sc_start(100, SC_NS);sc_close_vcd_trace_file(tf);cout<<"Finished at time " << sc_time_stamp() <<endl;return 0;}

另外: 

  • 激励数据可以从文件中读取,然后加载到被测设计中。
  • 还有一种激励是响应性激励,这种类型的激励源所生成的下一个激励取决于被测平台的当前状态。换言之,测试平台会根据被测设计的状态产生相应的激励。如进行数的阶乘计算的阶乘设计。

8.4 监视行为

        监视行为包括:

1)判断仿真结果是否正确

        将一个向量施加到被测设计的输入端口,在指定时间后,在输出端口进行采样,然后验证输出响应与期望值是否一致。

2)把结果保存到文本文件中

        通过使用C++语言中文件写入(输出流)功能,可将被测设计的输出值保存到文本文件中,需要注意的是:当打印数值时,打印的是当前时刻的信号值,而不是按计划在下一个∆时刻被赋的值。

8.5 更多示例

测试平台的示例demo将包括如下。将用单独的博文分别介绍。

  • 触发器
  • 带同步输出的多路选择器
  • 全加器
  • 周期节拍级仿真

8.6 在sc_main内的语句顺序

        SystemC对函数sc_main()中语句出现的先后顺序是敏感的。sc_main()函数基本上是一段有序程序,即按顺序执行的程序,因此期望程序的语句是有一定顺序的:

  • 所有模块引用和互连必须出现在调用任何仿真波形记录函数之前。
  • 在仿真启动之前,必须首先打开仿真波形的记录文件,然后再调用记录仿真波形的函数。
  • 若使用sc_set_time_resolution()方法来改变默认的时间分辨率(1ps),则该方法必须出现在任何sc_time对象被创建之前。
  • 在调用sc_start()之后不可以再出现模块的实例调用

8.7 跟踪记录集合类型

        sc_trace()方法被预定义用于SystemC类型和其他的C++标量类型。为了记录数组或者结构类型,必须编写自己的sc_trace()重载方法来记录单个部件的值。

        请考虑下面这个数组的声明,若想使用sc_trace()函数来记录reg_file的变化,则必须定义如下重载函数类型。

bool reg_file[NUM_BITS];
const int MAXLEN = 8;
void sc_trace(sc_trace_file *tfile, bool *v, const sc_string &name, int arg_length){char mybuf[MAXLEN];for(int j = 0; j<arg_length; j++){sprintf(mybuf, "[%d]", j);sc_trace(tfile, v[j], name+mybuf);}
}

        上述声明之后,就可以用以下语句调用sc_trace函数来记录仿真的波形了。

sc_trace(tf, reg_file, "reg_file", NUM_BITS);

        如果不想编写独立的sc_trace()重载函数,也可将上面的功能简单的按行写到(inline)函数sc_main()中,而不须再调用sc_trace()函数来记录reg_file的变化。

        借助于模板(template)可以使sc_trace()函数适用于任何类型的数组。下面这段代码假设这两个数组的元素类型允许通过调用sc_trace()函数来记录它们的变化。

template <class T>
void sc_trace (sc_trace_file *tfile, const T array_var[], const sc_string &name, int arg_length){for (int j = 0; j < arg_length; j++){sc_trace(tfile, array_var[j], name + "." + sc_string:: to_string("%d", j));}
}//调用的示例
sc_signal <float> qms[4];
int mlef[8];sc_trace(tfile, qms, "qms", 4);
sc_trace(tfile, mlef, "mlef", 8);

        对结构也可以进行类型的跟踪记录。可以编写一个sc_trace()重载方法,也可以只对个别成员编写sc_trace()调用来实现对结构的跟踪记录。若信号是结构类型的,则必须提供带其它重载操作符的sc_trace()重载方法。

struct packet{sc_uint<2> packet_id;bool packet_state;
};//为packet类型编写的sc_trace()重载方法
void sc_trace(sc_trace_file *tfile, const packet&v, const sc_string &name){sc_trace(tfile, v.packet_id, name + ".packet_id");sc_trace(tfile, v.packet_state, name +".packet_state");
}

        有了上述函数声明语句后,就能以如下形式调用sc_trace()方法了。

//集合类型信号
sc_signal <packet> saved;
sc_trace(tf, saved, "saved");

8.8 跟踪记录枚举类型

        SystemC提供了记录枚举类型值的功能。不过没有什么特别的地方,使用C++编码风格即可。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/107329.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

论文阅读:Rethinking Range View Representation for LiDAR Segmentation

来源ICCV2023 0、摘要 LiDAR分割对于自动驾驶感知至关重要。最近的趋势有利于基于点或体素的方法&#xff0c;因为它们通常产生比传统的距离视图表示更好的性能。在这项工作中&#xff0c;我们揭示了建立强大的距离视图模型的几个关键因素。我们观察到&#xff0c;“多对一”…

JOSEF约瑟 漏电继电器 JD1-200 工作电压:380V 孔径:45mm 50~500mA

JD1系列漏电继电器 系列型号 JD1-100漏电继电器 JD1-200漏电继电器 JD1-250漏电继电器 JD1系列漏电继电器原为分体式固定式安装&#xff0c;为适应现行安装场合需要&#xff0c;上海约瑟继电器厂在产品原JD1一体式漏电继电器基础上进行产品升级&#xff0c;开发出现在较为…

【Rust基础①】基本类型、所有权与借用、复合类型

文章目录 1 基本类型1.1 数值类型1.1.1 Rust 中的内置的整数类型&#xff1a;1.1.2 浮点类型1.1.3 数学运算1.1.4 位运算1.1.5 序列(Range) 1.2 字符、布尔、单元类型1.3 语句和表达式1.4 函数 2 所有权与借用2.1 栈(Stack)与堆(Heap)2.2 所有权原则2.2.1 转移所有权2.2.2 克隆…

【Redis】Java Spring操作redis

目录 引入Redis依赖StringRedisTemplate使用String使用List使用Set使用hash使用zset 引入Redis依赖 StringRedisTemplate 此处RedisTemplate是把这些操作Redis的方法&#xff0c;分成了几个类别&#xff0c;分门别类的来组织的。 此处提供的一些接口风格&#xff0c;和原生的Re…

IP 协议的相关特性(部分)

IP 协议的报文格式 4位版本号&#xff1a; 用来表示IP协议的版本&#xff0c;现有的IP协议只有两个版本&#xff0c;IPv4&#xff0c;IPv6。 4位首部长度&#xff1a; 设定和TCP的首部长度一样 8位服务类型&#xff1a; &#xff08;真正只有4位才有效果&#xff09;&#xf…

Linux C/C++ 嗅探数据包并显示流量统计信息

嗅探数据包并显示流量统计信息是网络分析中的一种重要技术&#xff0c;常用于网络故障诊断、网络安全监控等方面。具体来说&#xff0c;嗅探器是一种可以捕获网络上传输的数据包&#xff0c;并将其展示给分析人员的软件工具。在嗅探器中&#xff0c;使用pcap库是一种常见的方法…

【TensorFlow2 之014】在 TF 2.0 中实现 LeNet-5

一、说明 在这篇文章中&#xff0c;我们将展示如何在 TensorFlow 中实现像 \(LeNet-5\) 这样的基础卷积神经网络。LeNet-5 架构由 Yann LeCun 于 1998 年发明&#xff0c;是第一个卷积神经网络。 数据黑客变种rs 深度学习 机器学习 TensorFlow 2020 年 2 月 29 日 | 0 …

AUTOSAR组织发布20周年纪念册,东软睿驰NeuSAR列入成功案例

近日&#xff0c;AUTOSAR组织在成立20周年之际发布20周年官方纪念册&#xff08;20th Anniversary Brochure&#xff09;&#xff0c;记录了AUTOSAR组织从成立到今天的故事、汽车行业当前和未来的发展以及AUTOSAR 伙伴关系和合作在重塑汽车方面的作用。东软睿驰提报的基于AUTOS…

行情分析——加密货币市场大盘走势(10.16)

目前大饼再次止稳&#xff0c;并开始向上攀升&#xff0c;目前MACD来看也是进入了多头趋势。重新调整了蓝色上涨趋势线&#xff0c;目前来看这次的低点并没有跌破上一个低点&#xff0c;可以认为是上涨的中继。注意白天的下跌回调。 以太目前也是走了四连阳线&#xff0c;而MAC…

关于Skywalking Agent customize-enhance-trace对应用复杂参数类型取值

对于Skywalking Agent customize-enhance-trace 大家应该不陌生了&#xff0c;主要支持以非入侵的方式按用户自定义的Span跟踪对应的应用方法&#xff0c;并获取数据。 参考https://skywalking.apache.org/docs/skywalking-java/v9.0.0/en/setup/service-agent/java-agent/cust…

STM32 ---- 再次学习STM32F103C8T6/STM32F409IGT6

目录 一、环境搭建及介绍 关于STM32基础介绍 新建工程 外设案例 LED流水灯 蜂鸣器 上拉电阻和下拉电阻知识 电压比较器 c语言基础知识 类型、结构体、枚举 类型int8_t int16_t int32_t 宏替换 #define 和typedef用法 结构体两种填充方法 和 命名规则 枚举用法 常用…

uniapp中全局页面挂载组件(H5)

前言 我们已经学习了 uniapp中全局页面挂载组件&#xff08;小程序&#xff09; 有些小伙伴问在H5怎么做那让我们试一试 直接上代码 //引用组件 import dialog from ./index.vue; //我这里要把小程序的方法和h5方法写一起所以用了混入 import mixins from ./mixins.js //使用…

ElementUI编辑表格单元格与查看模式切换的应用

需求&#xff1a;有时候在填写表单的时候&#xff0c;想要在输入的时候是input输入框的状态&#xff0c;但是当鼠标移出输入框失去焦点时&#xff0c;希望是查看的状态&#xff0c;这种场景可以通过 v-if实现 vue2ElementUi里面使用如下&#xff1a; 1.el-table标签注册 cell-…

GitLab(1)——GitLab安装

目录 一、使用设备 二、使用rpm包安装 Gitlab国内清华源下载地址&#xff1a; ①下载命令如下&#xff1a; ②安装命令如下&#xff1a; ③删除rpm包 ④配置 ⑤重载 ⑥重启 ⑦配置自启动 ⑧打开8989端口并重启防火墙 三、GitLab登录 ①访问GitLab的URL ②输入用户…

如何实现 Es 全文检索、高亮文本略缩处理(封装工具接口极致解耦)

如何实现 Es 全文检索、高亮文本略缩处理 前言技术选型JAVA 常用语法说明全文检索开发高亮开发Es Map 转对象使用核心代码 Trans 接口&#xff08;支持父类属性的复杂映射&#xff09;Trans 接口可优化的点高亮全局配置类如下真实项目落地效果为什么不用 numOfFragments、fragm…

203、RabbitMQ 之 使用 direct 类型的 Exchange 实现 消息路由 (RoutingKey)

目录 ★ 使用direct实现消息路由代码演示这个情况二ConstantUtil 常量工具类ConnectionUtil 连接RabbitMQ的工具类Publisher 消息生产者测试消息生产者 Consumer01 消息消费者01测试消费者结果&#xff1a; Consumer02 消息消费者02测试消费者结果&#xff1a; 完整代码&#x…

微信小程序框架---详细教程

&#x1f3ac; 艳艳耶✌️&#xff1a;个人主页 &#x1f525; 个人专栏 &#xff1a;《Spring与Mybatis集成整合》《Vue.js使用》 ⛺️ 越努力 &#xff0c;越幸运。 目录 1.框架 1.1响应的数据绑定 1.2.页面管理 1.3.基础组件 1.4.丰富的 API 2.视图层 View 2.1.介绍 …

Jmeter脚本参数化和正则匹配

我们在做接口测试过程中&#xff0c;往往会遇到以下几种情况 每次发送请求&#xff0c;都需要更改参数值为未使用的参数值&#xff0c;比如手机号注册、动态时间等 上一个接口的请求体参数用于下一个接口的请求体参数 上一个接口的响应体参数用于下一个接口的请求体参数&#…

【09】基础知识:React组件的生命周期

组件从创建到死亡它会经历一些特定的阶段。 React 组件中包含一系列勾子函数&#xff08;生命周期回调函数 <> 生命周期钩子函数 <> 生命周期函数 <> 生命周期钩子&#xff09;&#xff0c;会在特定的时刻调用。 我们在定义组件时&#xff0c;会在特定的生…

一文理解登录鉴权(Cookie、Session、Jwt、CAS、SSO)

1 前言 登录鉴权是任何一个网站都无法绕开的部分&#xff0c;当系统要正式上线前都会要求接入统一登陆系统&#xff0c;一方面能够让网站只允许合法的用户访问&#xff0c;另一方面&#xff0c;当用户在网站上进行操作时也需要识别操作的用户&#xff0c;用作后期的操作审计。…