这是诱人的逻辑。如果这些片段是好的,那么整体,也就是已知好的片段的组合,一定是好的。
我小时候也是这么想的。橙汁很好;麦圈很好。因此,用橙汁代替牛奶可以提供美味的早餐。
错了。这是我至今还记得的一课。我一直都说不清楚为什么这两件事并没有一起起作用——没有明显的原因;他们就是没有。
再举一个例子:举8只温顺的狗。把它们放在一起,周围没有人(或者至少没有它们尊敬的人),让它们自由漫步。假设它们不互相争斗——事实上,特别是如果它们不争斗,如果它们都能很好地合作——那么,作为一个群体,它们很可能会制造出它们各自都不会考虑的各种破坏。虽然这与狗群心态有关,但它强化了一个事实,即好成分的组合并不总是会产生好结果。
我相信我们都以这样或那样的方式学到了这一课。然而,在必要的时候,我们很容易依赖这种逻辑。复杂的soc是由单独测试的块的组合创建的。甚至连互连都经过了测试,所以,故事应该继续,把它们放在一起就会起作用。
坦率地说,我们可能知道这有点逃避,但是,考虑到这些系统的复杂性,并且没有明显的方法来处理它,几乎就像我们需要这个小花招,以便在不完全崩溃的情况下发布系统。但事实是,“好东西的总和等于好东西”的同一性尚未得到证实。事实上,情况比这更糟:事实往往证明这是错误的,任何接到“我们的新硅有问题”电话的人都可以证明这一点。
对于芯片设计来说,有一个主要的新元素贡献了一个新的复杂性维度:软件。软件必须在录制之前进行测试——考虑到仅仅启动Linux就需要多少行代码,这不是一件容易的事情。这就是虚拟平台、仿真和硬件仿真加速的用武之地——您可以运行真正的软件来检查它在系统中的工作方式。
但是,根据Breker的Adnan Hamid的说法,被测试的典型软件都有一些局限性。在很大程度上,它是应用软件——这很好;找出已知的主要用例是显而易见和重要的。但它往往不强调架构或硬件。单独的压力测试可能会挑战处理器或其他局部元素,但Breker的论点是,很少有测试从芯片输入到整个系统(处理器只是其中的一部分),再到实际输出。
这种整体压力测试正是Breker的TrekSoC工具的目的。给定一组场景,我们的想法是让工具自动创建一套测试,挑战操作的各个角落。在场景中,工作是预先完成的——这可以在磁带录制之前很久就完成(可能是最好的完成)。它也可以在体系结构测试期间使用,当您仍然在事务级别工作,以便在实现开始之前从概念上验证系统时。
你可以把它想象成一个约束随机元素的层次结构。底层是低级的“服务”,比如内存管理、中断和轮询、调度和寄存器访问。随机场景可以在这些基础上构建,以服务于下一层,在那里驱动程序将使用它们。
这些驱动程序还将具有随机的场景,并且它们可以对低级场景施加约束,这样您就不会在无意义的情况下浪费测试(或得到失败的结果)。驱动场景供养应用场景,应用场景供养性能场景。
给定这些模型,测试是通过假定输入的结果(即一组输出),然后使用布尔求解器创建测试来创建的。这些测试与将要运行的实际应用程序没有任何关系——它们只是作为一个整体来测试系统并发现任何弱点。
Hamid使用的一个例子是,在中断触发之前,将一段数据写入内存。因为导致数据写入的代码已经在中断之前执行,所以通常会假设数据实际上已经写入,并且中断服务例程可以指望正确的数据已经就位。但是在具有片上网络互连结构的系统中,延迟可能是这样的,即请求了数据写入指令,但在中断之前没有完成。现在你有一个数据一致性的问题。
它们还针对多核问题,如死锁、活动锁和缓存一致性。这些区域很难用应用程序代码进行测试,而应用程序代码可能表现得非常好。TrekSoC表现不佳:它可以专门创建针对这类问题的测试,以查看系统是否完好无损。
测试代码本身是在裸机上运行的,任何操作系统调用都会被捕获并重新路由,而TrekSoC则充当了为这些调用提供服务的“邪恶”操作系统。这使代码尽可能地接近被测试的子系统,但也可以节省宝贵的测试时间,因为没有操作系统必须启动。
测试的形式取决于目标。在早期,当进行架构评估时,它们可以转换为IP单元测试的事务。在流程的后面,它们生成带有卸载和测试平台以及要运行的代码的RTL。卸载作为本地代码库实现,处理内存观察、“printf”命令、输入刺激和输出检查。
从抽象测试的角度来看,完整的模型提供了刺激、结果检查和覆盖率统计数据,使其完全独立。测试的实际流(特别是随机性质)在测试生成时确定,而不是在运行时确定。任何产生的覆盖缺口都可以通过指导工具为用于描述场景的流图上的特定未覆盖节点创建测试来解决。
如果这一切都有效,那么它给了你一种确保你不会扔掉早餐重新开始的方法。或者邻居们不会都抱怨他们的垃圾被翻了,他们的猫都被困在树上了。最棒的是,你不会在第一块硅之后接到可怕的电话。
更多信息:
你目前如何处理这个问题,确保你已知的好的部分能组合成一个好的整体?