【数据通路的时钟周期(程序分析)】( C++ | 拓扑排序 | DP | AOV | DAG最长路 | 数字电路 | 时序分析)

 时钟信号:      

        执行部件之间的数据通路调度,是由CPU内的时序发生器所产生的微操作时间信号控制,受到时钟的驱动。

        时序发生器根据时钟信号的脉冲,产生微操作时间信号,这些信号用于精确地控制各个部件的动作和数据的传输。微操作时间信号可以用于各个执行部件的使能、数据选择和操作控制等。

        时钟信号作为CPU系统中的基准信号,提供了统一的时间参考。时钟信号固定的频率周期确保了CPU内部各个部件按照同步的节奏进行操作和通信。时钟信号的变化驱动着时序发生器的工作,使得微操作时间信号按照预定的时序顺序产生。

 D触发器:      

        触发器是时序逻辑电路的基本单元,用来存储1位2进制信息,具有记忆和存储功能,其信息由双稳态电路来保存。

        D触发器是一种最简单的触发器,在触发边沿到来时,将输入端的值存入其中,并且这个值与当前存储的值无关。

        在两个有效的脉冲边沿之间,D的跳转不会影响触发器存储的值,但是在脉冲边沿到来之前,输入端D必须有足够的建立时间,保证信号稳定。

 

 考虑这个场景:

两个寄存器单元R1,R2之间通过一排平行等位宽的D触发器桥连,分析该数据通路(IPO)的时钟信号的周期范围。
 

给出如下参数:

Tsu      :   触发器建立时间 Time of setup

Th        : 触发器保持时间 Time of hold

T          : 电路的工作周期

Tco      :   时钟输出延迟 Time of clock output

Tskew : 时钟偏斜(clock skew),又称为时钟偏移,是指时钟信号到达数字电路各部分所用时间差异。

Tcomb: 组合逻辑的延迟。

则电路的工作周期 满足如下关系:

保持时间不违例:Tco+Tcomb-Tskew > Th

建立时间不违例:T+Tskew > Tco+Tcomb+Tsu

所以该问题可以转化为DAG(有向无环图)的最长关键路径问题,可以使用拓扑排序和动态规划的方法进行分析。

有向无环图即为上述数据通路:R1 - D触发器阵列 - R2

 首先定义D触发器的基本参数

typedef int ns_t;//微秒单位

struct D_trigger{
	ns_t Tsu;//建立时间
	ns_t Th;//保持时间
	ns_t Tco;//延迟时间
	ns_t Tskew { 0U };//偏移时间
};

 设置逻辑门部件的时延参数映射(单位为1T/ns)

enum class GATE : unsigned char
{ IN, OUT,//假象起点和终点,统一入口和出口
  D, CLK,//D:数据端引脚,CLK:时钟接口
  Q, NQ,//Q输出,NQ:反相输出
  AND, OR, NOT,//与或非
  NAND, NOR, XOR };//反相与或、异或
std::unordered_map<GATE, ns_t> delay_hash
{//相关逻辑门部件的连通时延
{GATE::D,   0U},
{GATE::CLK, 0U},
{GATE::Q,   0U},
{GATE::NQ,  0U},
{GATE::AND, 1U},
{GATE::OR,  1U},
{GATE::NOT, 2U},
{GATE::NAND, 3U},
{GATE::NOR,  3U},
{GATE::XOR, 3U} };

 通过给每个逻辑门部件编上编号,建立联通关系,形成单向图

可以看到总共13个逻辑单元,按照编号顺序存储

constexpr std::size_t GATES { 13U };//一共13个元器件
GATE gates[GATES]
{按照编号顺序存储数据通路
	GATE::IN,
	GATE::D,
	GATE::CLK,
	GATE::NOT,
	GATE::OR,
	GATE::NOT,
	GATE::NOR,
	GATE::NOR,
	GATE::NOR,
	GATE::NOR,
	GATE::Q,
	GATE::Q,
	GATE::OUT,
};

建图

int indeg[GATES] {};//入度
struct graph{
	struct edge{
		int __forward__;
		int __next__;
	} edges[32U];//链式向前星存图

	int hG[GATES] {};
	std::size_t tot {};

	graph(void) noexcept{ std::memset(hG, -1, sizeof hG); }

	void insert(int from, int to) noexcept{
		edges[tot]
			= (edge){ __forward__ : to,
					  __next__ : hG[from] };
		hG[from] = tot++;
		++indeg[to];
	}
} G;
void construct(void){
//按照数据通路示意图建图
	G.insert(0, 1);
	G.insert(0, 2);
	G.insert(2, 3);
	G.insert(2, 4);
	G.insert(3, 4);
	G.insert(1, 5);
	G.insert(5, 7);
	G.insert(4, 6);
	G.insert(4, 7);
	G.insert(6, 8);
	G.insert(7, 9);
	G.insert(8, 10);
	G.insert(9, 11);
	G.insert(10, 12);
	G.insert(11, 12);
}

 拓扑排序得到拓扑序列

	std::queue<int> q;
	for(auto i {0U}; i < GATES; ++i)
		if(!indeg[i]) q.push(i);
		
	while(!q.empty()){
		int current = q.front();
		q.pop();
		
		for(int i {G.hG[current]}; ~i; i = G.edges[i].__next__)
			if(! --indeg[G.edges[i].__forward__])
				q.push(G.edges[i].__forward__);
				
		topology[counter++] = current;
	}
	
	std::puts("topology sequence:");
	for( auto i {0U}; i < GATES; ++i)
		std::printf("[G%d]%c", topology[i], " \n"[i == GATES]);

动态规划得到最大时延的通路,和最小时延的通路

std::memset(maximal_delay, -1, sizeof maximal_delay);
	std::memset(minimal_delay, 0x3f, sizeof minimal_delay);
	maximal_delay[0] = minimal_delay[0] = 0;
	for( auto i {0U}; i < GATES; ++i){
		int current { topology[i] };
		
		for(int u {G.hG[current]}; ~u; u = G.edges[u].__next__){
			int next = G.edges[u].__forward__;
			
			if(maximal_delay[current] + delay_hash[gates[current]]
			>  maximal_delay[next]){
				maximal_delay[next]
					= maximal_delay[current] + delay_hash[gates[current]];
				maximal_delay_path_previous[next] = current;
			}
			
			if(minimal_delay[current] + delay_hash[gates[current]]
			<  minimal_delay[next]){
				minimal_delay[next]
					= minimal_delay[current] + delay_hash[gates[current]];
				minimal_delay_path_previous[next] = current;
			}
		}
	}

通过递归工作站倒序输出

void print_maximal_delay_path(int current){
	if(!~current) return (void)std::printf("\n\n");
	print_maximal_delay_path(maximal_delay_path_previous[current]);
	std::printf("[G%d] --> ", current);
}

void print_minimal_delay_path(int current){
	if(!~current) return (void)std::printf("\n\n");
	print_minimal_delay_path(minimal_delay_path_previous[current]);
	std::printf("[G%d] --> ", current);
}

程序的执行结果

完整代码

#include <unordered_map>
#include <queue>
#include <cstring>
#include <cstdio>

typedef int ns_t;//微秒单位

struct D_trigger{
	ns_t Tsu;
	ns_t Th;
	ns_t Tco;
	ns_t Tskew { 0U };
};

enum class GATE : unsigned char
{ IN, OUT,
  D, CLK,
  Q, NQ,
  AND, OR, NOT,
  NAND, NOR, XOR };
std::unordered_map<GATE, ns_t> delay_hash
{
{GATE::D,   0U},
{GATE::CLK, 0U},
{GATE::Q,   0U},
{GATE::NQ,  0U},
{GATE::AND, 1U},
{GATE::OR,  1U},
{GATE::NOT, 2U},
{GATE::NAND, 3U},
{GATE::NOR,  3U},
{GATE::XOR, 3U} };
  
constexpr std::size_t GATES { 13U };
GATE gates[GATES]
{
	GATE::IN,
	GATE::D,
	GATE::CLK,
	GATE::NOT,
	GATE::OR,
	GATE::NOT,
	GATE::NOR,
	GATE::NOR,
	GATE::NOR,
	GATE::NOR,
	GATE::Q,
	GATE::Q,
	GATE::OUT,
};


int indeg[GATES] {};
struct graph{
	struct edge{
		int __forward__;
		int __next__;
	} edges[32U];

	int hG[GATES] {};
	std::size_t tot {};

	graph(void) noexcept{ std::memset(hG, -1, sizeof hG); }

	void insert(int from, int to) noexcept{
		edges[tot]
			= (edge){ __forward__ : to,
					  __next__ : hG[from] };
		hG[from] = tot++;
		++indeg[to];
	}
} G;

int topology[GATES] {};
int counter {};
int maximal_delay[GATES] {};
int minimal_delay[GATES] {};
int maximal_delay_path_previous[GATES] {};
int minimal_delay_path_previous[GATES] {};

void print_maximal_delay_path(int current){
	if(!~current) return (void)std::printf("\n\n");
	print_maximal_delay_path(maximal_delay_path_previous[current]);
	std::printf("[G%d] --> ", current);
}

void print_minimal_delay_path(int current){
	if(!~current) return (void)std::printf("\n\n");
	print_minimal_delay_path(minimal_delay_path_previous[current]);
	std::printf("[G%d] --> ", current);
}

void construct(void){
	G.insert(0, 1);
	G.insert(0, 2);
	G.insert(2, 3);
	G.insert(2, 4);
	G.insert(3, 4);
	G.insert(1, 5);
	G.insert(5, 7);
	G.insert(4, 6);
	G.insert(4, 7);
	G.insert(6, 8);
	G.insert(7, 9);
	G.insert(8, 10);
	G.insert(9, 11);
	G.insert(10, 12);
	G.insert(11, 12);
}

int main(void){
	construct();
	
	std::queue<int> q;
	for(auto i {0U}; i < GATES; ++i)
		if(!indeg[i]) q.push(i);
		
	while(!q.empty()){
		int current = q.front();
		q.pop();
		
		for(int i {G.hG[current]}; ~i; i = G.edges[i].__next__)
			if(! --indeg[G.edges[i].__forward__])
				q.push(G.edges[i].__forward__);
				
		topology[counter++] = current;
	}
	
	std::puts("拓扑排序序列:\n");
	for( auto i {0U}; i < GATES; ++i)
		std::printf("[G%d]%c", topology[i], " \n"[i == GATES]);

	std::memset(maximal_delay, -1, sizeof maximal_delay);
	std::memset(minimal_delay, 0x3f, sizeof minimal_delay);
	maximal_delay[0] = minimal_delay[0] = 0;
	for( auto i {0U}; i < GATES; ++i){
		int current { topology[i] };
		
		for(int u {G.hG[current]}; ~u; u = G.edges[u].__next__){
			int next = G.edges[u].__forward__;
			
			if(maximal_delay[current] + delay_hash[gates[current]]
			>  maximal_delay[next]){
				maximal_delay[next]
					= maximal_delay[current] + delay_hash[gates[current]];
				maximal_delay_path_previous[next] = current;
			}
			
			if(minimal_delay[current] + delay_hash[gates[current]]
			<  minimal_delay[next]){
				minimal_delay[next]
					= minimal_delay[current] + delay_hash[gates[current]];
				minimal_delay_path_previous[next] = current;
			}
		}
	}
	maximal_delay_path_previous[0] = -1;
	minimal_delay_path_previous[0] = -1;
	
	std::puts("\n\n最大时延通路:");
	print_maximal_delay_path(GATES - 1);
	std::puts("\n\n最小时延通路:");
	print_minimal_delay_path(GATES - 1);
	
	std::printf("\n\n最大时延:\t%dT\n", maximal_delay[GATES-1]);
	std::printf("\n\n最小时延:\t%dT\n", minimal_delay[GATES-1]);
	
	return 0;
}
  

  • 12
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XNB's Not a Beginner

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值