PartiCo的数据结构选择
作为没写过软件的数据结构小白,对于开发新工具PartiCo的数据结构选择进行了大量的思想斗争而不得其果,只好从数据结构基础开始这个选择的过程。
数据结构是数据元素和数据元素之间关系的组织形式。
数据结构包含存储结构,逻辑结构,以及对数据的操作。
存储结构分为四种基本形式:
(1)顺序存储方式。数据元素顺序存放,每个存储结点只含一个元素。存储位置反映数据元素间的逻辑关系。存储密度大,但有些操作(如插入、删除)效率较差。
(2)链式存储方式。每个存储结点除包含数据元素信息外还包含一组指针。指针反映数据元素间的逻辑关系。这种方式不要求存储空间连续,便于动态操作(如插入、删除等),但存储空间开销大,且不适用于随机查找。
(3)索引存储方式。除数据元素存储在一内存空间外,尚需建立一个索引表,索引表中索引指示存储结点的存储位置,兼有静态和动态特性。
(4)散列存储方式。将关键字散列在地址空间内,并将散列函数的值解释成关键字所在元素的存储地址,这种存储方式称为散列存储。其特点是存取速度快,只能按关键字随机存取,不方便顺序存取。
逻辑结构也分为四种基本形式:
(1)集合
(2)线性结构
(3)树形结构
(4)图形或网状结构。
目前条件下,我们几乎可以不关心内存空间的大小、连续性,只追求查找和其他操作的效率。
一个大致的判断,PartiCo的存储结构可以选取 索引存储方式 或者 散列存储方式,或者混合形式;
逻辑结构可以选取 树形结构 或者 图形/网状结构。
简单来看,一种数据结构在语言上可以用结构体(struct)或者类(class)来表示,我们用python,所以用class表示。
PartiCo在操作大多在两个层面上:
1. instance数据元素的查找和修改
2. instance之间关系的查找和修改
不妨把这两层看作是两层数据结构,按照之前的预想
第一层是class instance(instance含层次保证唯一性)
value主要包括
a.例化形式(module和param)
b.跟其他instance的connection
c.资源(reg, comb, mem)
存储结构可以选择散列存储,查询最快,索引在这一层暂不考虑
逻辑结构可以无视(元素之间互相不依赖)
基本操作是插入(初始化),查找,修改value(划分导致),删除(删除dft/lp连接)
第二层是class instance_tree(system)
value主要就是每个instance的指针,或者说完整层次。
逻辑结构考虑到网状或图形结构虽然肯定能用,但自由度太大,对算法要求比较高,对我们这种小白来说不太适合
可以选择更好实现的树形,同时符合自顶向下的逻辑关系。
树有四种表示方法:
树形/文氏图/凹入表/广义表
凹入表其实就是iconnect的hierarchy形式,由此可见树形结构跟RTL结构是天然匹配的
|CORE_TOP
|DSPS
|DSPS_DSP0
|DSPS_DSP1
|CPUS
|CPUS_CPU0
......
而我们也可以继承凹入表的形式来表达instance_tree的hierarchy,即FPGA_partition.txt。
树形结构的存储结构可以选择的有很多,以二叉树为例,可以选择二叉链式或者三叉链式:
二叉链:每个节点链到下面的左右子节点
三叉链:每个节点能够反向访问父结点
因为我们肯定需要访问父结点,并且对空间不care,若考虑用二叉树,显然我们要选三叉链式的二叉树。
那么我们到底应该选用哪种存储结构呢?这个问题留到后面。
基本操作是插入(asic代码自顶向下解析),查找,修改value(主要是修改层次即),删除。
PartiCo的input:
FPGA_partition.txt (类似于iconnect中的hierarchy部分,让我们把auto partition跟PartiCo分开吧)
ASIC RTL的gtech网表
ASIC RTL的层次结构和例化形式,已尝试可以用verdi生成后再用脚本转成我们所需要的格式。
PartiCo的DB1:
instance_tree asic_system
instance asic_instance1
instance asic_instance2
instance asic_instance3
PartiCo的DB2:
instance_tree fpga_system
instance fpga_instance1
instance fpga_instance2
instance fpga_instance3
PartiCo的output:
FPGA RTL代码
散列是确定的,即hash表,可是 --
树形结构有这么多种,哪种最适合呢,既然我们首要选择标准是要算得快,那么是要算什么呢?
到这,我们的问题转化为:
1. 树形有哪些存储结构形式,这些结构的特点分别是什么,适合什么样的操作?
可参考SQL对树形结构的四种存储方法,转知乎上卢钧轶的一个回答:
怎样在 MySQL 表中存储树形结构数据?
一般比较普遍的就是四种方法:(具体见 SQL Anti-patterns这本书)
Adjacency List:每一条记录存parent_id
Path Enumerations:每一条记录存整个tree path经过的node枚举
Nested Sets:每一条记录存 nleft 和 nright
Closure Table:维护一个表,所有的tree path作为记录进行保存。
结构比较如下:
2. PartiCo需要对instance做哪些基本操作?每种基本操作分别有多大概率要用到?
这个答案需要如下考虑如下方面的组合:
算法 + 所需操作用到的概率 + 大操作分解成基本操作
其中算法包括正向解析算法(PartiCo.input -> DB1)和反向转化算法(DB2 -> 划分后的RTL代码)