深入解析PSI-L协议:SoC内部高效数据流的设计思想与实战

发布时间:2026/7/29 15:08:32
深入解析PSI-L协议:SoC内部高效数据流的设计思想与实战 1. PSI-L协议重新定义SoC内部的数据高速公路在复杂的片上系统SoC设计里数据如何在几十个甚至上百个功能模块之间高效、有序地流动一直是个核心挑战。传统基于物理地址的互连方式就像在一个大城市里每辆快递车数据包都必须携带一个精确到门牌号的地址物理地址然后依赖一个庞大的中央交通指挥系统交叉开关或总线来寻路。当模块数量激增、数据流变得错综复杂时这个“中央交通指挥系统”就会成为瓶颈导致拥堵、延迟和硬件资源的浪费。我接触过不少嵌入式项目尤其是在处理高速网络数据、图像流或者多核间通信时传统的总线或NoC片上网络架构在灵活性和效率上常常捉襟见肘。直到我在德州仪器TI的AM64x/AM243x这类高性能处理器中深入研究了其数据移动子系统DMSS才发现了一种更优雅的解决方案基于线程ID的数据包流式接口也就是PSI-L。PSI-L的本质是把数据流动的视角从“地址”切换到了“线程”。你可以把它想象成公司内部的高效物流系统。每个部门SoC模块不再关心包裹要送到哪个具体的工位物理地址而是为每个持续的数据流比如视频采集流、网络发包流、DMA传输流分配一个唯一的“工单号”或“流水线编号”这就是线程ID。所有包裹数据包只标记这个工单号然后扔进一个高速传送带PSI-L物理链路。传送带尽头有一个智能分拣中心DMSS0它只看工单号就能准确地把包裹分发到对应的处理流水线目标线程。这种方式彻底解耦了数据流与物理拓扑让数据移动变得极其灵活和高效。这套架构特别适合需要处理大量并发、实时数据流的场景比如工业通信网关、边缘AI推理设备、多通道视频处理系统等。如果你正在为如何设计一个高效、低延迟的模块间通信机制而头疼或者想理解现代SoC内部数据搬运的底层逻辑那么深入剖析PSI-L的设计思想绝对能给你带来全新的启发。接下来我将结合手册内容和实际工程经验为你层层拆解PSI-L的工作原理、配置方法以及那些手册里不会写的实战细节。2. 核心设计思想从物理寻址到逻辑路由的范式转变要理解PSI-L的价值我们必须先看清它要解决什么问题。在传统SoC互连中无论是AXI、AHB总线还是更复杂的NoC通信的核心是物理地址空间。发起方Initiator必须知道目标方Target的精确寄存器或内存映射地址。这种模式在简单系统中工作良好但当系统需要支持动态、多对多的数据流时问题就暴露了。2.1 传统架构的痛点与PSI-L的破局思路想象一个场景一个网络加速模块需要将收到的数据包通过DMA搬运到不同的内存区域处理后再由另一个视频编码模块取走。在传统架构下网络模块的DMA控制器需要被编程设定目标内存地址视频模块也需要知道从哪里读取数据。如果数据流路径需要动态改变例如根据数据包类型路由到不同的处理单元就需要CPU频繁地介入重新配置DMA的描述符或地址这带来了软件开销和延迟。PSI-L的破局之道在于引入了线程Thread这个逻辑抽象层。它不再暴露物理地址而是定义了一个全局的、逻辑的线程ID空间。每个数据流例如一个特定的DMA通道、一个消息队列或者一个直接IO隧道都被绑定到一个唯一的源线程ID或目的线程ID上。数据包只携带目的线程ID就像快递包裹上只写收件人姓名线程ID而不写家庭住址物理地址。所有的PSI-L接口都是点对点直接连接到中央的DMSS0模块由DMSS0内部完成基于线程ID的交换和路由。这种设计带来了几个根本性优势解耦与灵活硬件模块如PDMA、网络MAC只需知道它要和哪个“逻辑线程”通信而无需关心这个线程背后是哪个物理模块、位于哪个地址。数据流的重新路由例如将数据从核A的内存搬到核B的内存只需在中央的DMSS中重新配置线程映射关系前端模块的配置可以保持不变。硬件效率基于线程ID的交换可以在硬件上实现得非常高效。它本质上是一个查表操作比基于复杂地址译码和仲裁的总线访问更快也更易于实现高带宽、低延迟的交叉开关。自然的流控PSI-L为每个线程连接维护信用Credit机制。发送方必须在确认接收方有缓存空间即拥有信用时才能发送数据。这实现了基于流的、细粒度的反压控制防止一个慢速或阻塞的接收端拖垮整个链路这是保证实时性的关键。2.2 线程ThreadPSI-L通信的基石单元在PSI-L的语境下线程是一个需要彻底理解的核心概念。它不是一个软件意义上的执行线程而是一个完整的、带流控制的通信流。手册中将PSI-L的线程空间划分为两个连续的32K区域源线程ID范围 0x0000 - 0x7FFF。源线程负责发起请求事务、接收响应事务以及发送数据传输事务。你可以把它看作是数据的生产者或命令的发起者。目的线程ID范围 0x8000 - 0xFFFF。目的线程负责接收请求事务、发送响应事务以及接收数据传输事务。这是数据的消费者或命令的执行者。一个关键规则是数据只能从源线程流向目的线程或者响应从目的线程流回源线程。同类型线程之间源到源目的到目的不会发生传输。这形成了一个清晰、单向的通信模型。线程之间需要建立配对Pairing才能通信。这通过一个特殊的配对配置消息来完成并且只能在相同类型的线程发起者和目标之间进行。例如一个“队列管理消息”类型的源线程只能与一个“队列管理消息”类型的目的线程配对。这种强类型检查保证了通信语义的正确性。2.3 时间分片复用一条物理链路承载千军万马PSI-L最精妙的设计之一是让多条独立的逻辑数据流线程共享一条物理链路。这是通过数据相位粒度的时间分片复用实现的。这是什么意思呢它不是以整个数据包为单位进行切换而是在更细的“数据相位”粒度上进行交织。每个数据相位都带有一个类型标识符告诉接收方当前传输的是什么是数据包信息、直接IO读写信息、时间戳、软件信息、控制数据、有效载荷数据还是状态。举个例子假设线程A正在传输一个数据包这个包可能由多个数据相位组成。在传输完线程A的一个数据相位后硬件仲裁器可以立即切换到线程B传输它的一个数据相位然后再切回线程A传输下一个数据相位。这样从宏观上看线程A和线程B的数据包是同时、交织地在链路上传输的但从每个线程内部看它的数据相位序列是严格有序的。这种细粒度TDM的好处是极低的传输延迟和高的链路利用率。即使一个线程正在传输一个长数据包其他线程也无需等待整个包传完只需等待当前数据相位结束即可插入极大地减少了阻塞时间。3. PSI-L协议栈深度解析与工作流程理解了设计思想我们深入到协议层看看一个数据包是如何从源头抵达终点的。PSI-L的协议栈可以粗略分为两层底层的硬件握手和上层的信用流控。3.1 底层硬件握手与数据相位在物理连接层面PSI-L的发起方和目标方之间有一个低级别的硬件握手信号。这个握手通常是基于“有效-就绪”Valid-Ready机制的是阻塞式的。也就是说当发起方驱动数据有效时它必须等待目标方表明其已就绪接收传输才能发生。这种机制简单可靠确保了每个时钟周期数据传递的可靠性。每个在链路上传输的数据单元都伴随着丰富的控制信息这主要体现在数据相位类型标识符上。手册中列举的类型包括Packet Info数据包信息可能包含包长度、属性等元数据。Direct IO Write/Read Info用于隧道化总线事务的读写命令信息。Timestamp时间戳信息用于同步或调试。Software Info软件定义的信息字段。Control Data控制命令数据。Payload Data实际的有效载荷数据。Status状态信息如传输结束标志。这个类型标识符是接收方正确解析和处理数据流的关键。例如一个DMA传输可能以“DMA Transfer Request Message”类型开始接着是多个“Payload Data”类型的数据相位最后以一个“Status”类型相位结束。3.2 信用流控防止阻塞的守护神仅有硬件握手是不够的。如果接收端的缓冲区满了即使硬件握手就绪数据也无处安放会导致发送端空等进而可能阻塞共享同一链路的其他线程。这就是PSI-L引入信用机制的原因。信用流控的工作原理如下每个目的线程都会告知与之配对的源线程“我这里有N个缓冲单元可以接收数据”。这N就是初始信用值。每当源线程通过PSI-L向该目的线程成功发送一个数据单元通常是一个数据相位它就会消耗掉一个信用。当目的线程处理完一个数据单元空出缓冲区后它会通过反向通道响应消息向源线程“归还”一个信用。仲裁器的关键规则在每一个时钟周期决定哪个线程能使用链路时仲裁器不仅检查该线程是否有数据要发送还必须检查它是否拥有到达目的地的信用。只有两者都满足这个线程才有资格参与仲裁。这个机制完美解决了“无限期阻塞”的问题。一个线程不可能因为目的端处理缓慢而长期霸占链路因为它自己的信用会很快耗尽。一旦信用用光即使它有数据也会被仲裁器排除在外从而给其他有信用的线程让出通道。手册特别提到对于反向传输响应消息通常假设信用总是存在的因为响应一般很小且是请求触发的其缓存需求容易得到保障。3.3 仲裁协议链路上的交通警察PSI-L链路仲裁器的决策是一个多因素权衡的过程其目标是公平性和效率。在每个周期仲裁器会检查所有有待发送数据的源线程并依据以下因素做出选择数据就绪源线程是否有数据准备发送这是基本前提。信用存在该线程是否有到达目的线程的信用这是流控保障。流量优先级该线程当前所携带数据包的优先级。高优先级的线程如实时音频流应该获得更及时的服务。传输方向请求正向还是响应反向。通常响应消息反向会被赋予比请求消息正向更高的优先级这是为了快速释放请求端的资源避免请求端因等待响应而阻塞。仲裁器的工作流程可以概括为首先筛选出“数据就绪且信用充足”的候选线程然后在这些候选线程中优先选择反向传输的线程其次再根据预设的优先级从高到低选择正向传输的线程。这个动态的仲裁策略确保了高优先级流量和响应消息的低延迟同时通过信用机制保证了所有线程都能得到服务不会饿死。4. PSI-L的典型应用场景与线程类型PSI-L不是一个为单一功能设计的接口而是一个通用的数据移动载体。手册中明确了几种已定义的线程类型每种类型服务于不同的通信模式这体现了其设计的通用性。4.1 队列管理消息传输这是PSI-L在分布式处理中非常经典的应用。在现代多核/众核SoC中任务或数据包经常以“工作队列”的形式在核心、加速器之间传递。一个中央化的队列管理器QM维护着这些队列的状态。工作原理一个DMA客户端源线程需要向某个队列推送Push一个工作项。它通过PSI-L发送一个“QM Push Message”到中央队列管理器目的线程。这个消息里包含了队列ID和数据指针等信息。QM处理完后可能通过一个“QM Push Response Message”回复。同样一个客户端想从队列取Pop工作项就发送“QM Pop Message”。价值将队列操作抽象为标准的消息传递实现了计算单元与队列管理的解耦。任何模块只要支持PSI-L和QM消息协议就能参与全局的任务调度非常适合基于任务池的并行处理框架。4.2 直接IO隧道这个功能非常强大它允许将传统的、基于地址的CBASS可能是TI内部的一种总线协议兼容的事务通过PSI-L链路进行“隧道”传输。工作原理假设模块A需要通过一个标准的内存读写操作访问模块B的寄存器但两者之间没有直接的物理总线连接。模块A可以将这个读写请求包括地址、数据、操作类型打包成一个“Direct IO Write/Read Operation Message”通过PSI-L发送给模块B的一个代理模块目的线程。代理模块在本地执行这个总线事务然后将结果通过响应消息返回。价值这使得那些本身没有总线发起器能力的模块能够远程访问其他模块的资源极大地扩展了系统的互连灵活性。相当于在逻辑上“拉直”了系统拓扑简化了硬件设计。4.3 DMA控制与数据传输这是PSI-L在数据搬运子系统中的核心作用也是AM64x/AM243x中PDMA与中央DMSS协作的基础。DMA控制传输用于传递DMA传输描述符。例如一个中央的DMA通道控制器源线程需要启动一个传输它会将传输描述符源地址、目的地址、长度等通过“DMA Transfer Request Message”发送给远程的DMA传输控制器目的线程。DMA数据传输用于搬运实际的批量数据。例如一个网络适配器源线程收到数据包后通过“DMA Data Message”将数据包的有效载荷流式传输到中央DMA目的线程再由DMA写入内存。反之DMA从内存读取数据后也可以通过PSI-L流式传输给一个显示控制器目的线程。与PDMA的协作在TI的架构中外设DMAPDMA是一个轻量级的、靠近外设的DMA引擎它只负责与外设寄存器打交道通过VBUSP接口。而复杂的多维传输、内存访问则由强大的中央DMSS完成。PSI-L正是连接PDMA和DMSS的桥梁。PDMA将外设数据打包成PSI-L流发送给DMSS或者从DMSS接收PSI-L流并写入外设。这种异构分工做到了“物尽其用”简单任务由简单的PDMA处理复杂任务由强大的DMSS处理中间通过高效的PSI-L连接。5. PSI-L配置实战寄存器详解与编程模型理论讲得再多最终还是要落到配置和代码上。PSI-L的配置主要围绕两个核心线程配对和寄存器访问。所有配置都是通过一个特殊的配置代理模块完成的。5.1 配置代理与配置事务系统中存在一个或多个PSILCFG_PROXY模块。它是唯一有权发起配置读写事务的模块。你可以把它理解为PSI-L网络的“配置管理终端”。它使用一个专用的源线程可以向系统中任何其他源线程或目的线程的配置寄存器发起读写操作。配置事务也是通过PSI-L协议传输的但走的是独立的逻辑路径。一次配置写操作流程如下软件向PSILCFG_PROXY的寄存器写入目标线程ID、配置寄存器地址、数据和命令。PSILCFG_PROXY模块将这些信息组装成“Configuration Write Message”通过PSI-L发送给目标线程。目标线程收到后执行寄存器写入并返回一个“Configuration Write Response Message”。PSILCFG_PROXY收到响应更新状态可能产生中断通知软件完成。配置读操作类似只是最后返回的是读取的数据。手册中提到的PSIL_TO超时寄存器就是用来处理配置事务无响应的情况的这是一个重要的可靠性设计。5.2 关键配置寄存器解析我们以手册中列出的DMASS0_PSILCFG_0寄存器组为例看看如何操作配置代理。它的基地址是0x4813_0000。PSIL_CMDA寄存器这是命令寄存器A。PROXY_BUSY只读位。当配置代理正在处理一个读写事务时此位为1。软件在发起新事务前应查询此位是否为0。PROXY_DIR读写位。设置事务方向0表示写1表示读。PROXY_TOUT超时标志位。如果一次配置访问超时此位会被置1。这个位需要软件写0来清除这是一个常见的“写1清除”或“写0清除”模式在访问前最好先清除它。PROXY_THREAD_ID目标线程ID。你要配置哪个线程就把它的ID写到这里。PSIL_CMDB寄存器命令寄存器B。PROXY_BYTEN字节使能。对于32位寄存器访问通常设置为0xF全使能。PROXY_ADDRESS目标线程配置空间内的字地址。注意这是32位字对齐的地址偏移。例如要访问目标线程配置空间的0x10字节偏移处的寄存器这里应填写0x10 / 4 0x4。PSIL_WDATA寄存器要写入的数据。PSIL_RDATA寄存器读取到的数据。一个典型的配置写流程伪代码如下// 假设配置代理基地址为 PSILCFG_BASE volatile uint32_t *cmda (uint32_t*)(PSILCFG_BASE 0x100); volatile uint32_t *cmdb (uint32_t*)(PSILCFG_BASE 0x104); volatile uint32_t *wdata (uint32_t*)(PSILCFG_BASE 0x108); volatile uint32_t *rdata (uint32_t*)(PSILCFG_BASE 0x140); volatile uint32_t *timeout (uint32_t*)(PSILCFG_BASE 0x010); // 1. 检查并清除超时标志 if (*timeout (1 29)) { // 检查TOUT位 *timeout ~(1 29); // 写0清除超时标志 } // 2. 等待代理空闲 while (*cmda (1 31)) { // 等待PROXY_BUSY位为0 // 可加入超时或调度 } // 3. 设置目标线程ID (例如 0x8001一个目的线程) *cmda (0x8001 0xFFFF); // 设置PROXY_THREAD_ID字段 // 4. 设置命令B字节使能(0xF)和字地址(例如偏移0x0) *cmdb (0xF 28) | (0x0); // 假设写目标线程配置空间第一个寄存器 // 5. 设置要写入的数据 *wdata 0x12345678; // 6. 发起写操作设置方向为写(0)同时写PROXY_BUSY位启动事务 *cmda | (0 30) | (1 31); // PROXY_DIR0 (写), 置位PROXY_BUSY启动 // 7. 等待操作完成 while (*cmda (1 31)) { // 等待PROXY_BUSY变0 } // 8. 检查是否超时 if (*cmda (1 29)) { // 处理超时错误 *cmda ~(1 29); // 清除超时标志 }5.3 线程配对配置详解线程配对是PSI-L通信建立的前提。每个源线程都有一组可编程的寄存器用于配置它与哪个目的线程配对并启用数据流。这些寄存器正是通过上述配置代理进行访问的。配对的过程通常是确定线程类型和ID首先你需要查阅芯片的《系统线程映射表》手册中提到的System Thread Map找到你需要的功能模块如UART0的发送DMA通道对应的标准线程ID和类型。配置源线程通过配置代理向源线程的配置寄存器写入配对的目的线程ID并可能设置一些流控参数如初始信用数。配置目的线程同样配置目的线程的寄存器告知其缓冲能力这会影响信用计算并启用它。启用数据流在两端都配置好后通过寄存器启用线程。这里有一个非常重要的实践细节线程的启用顺序。通常应该先确保目的线程接收方已配置并准备好接收数据然后再启用源线程发送方。如果顺序反过来源线程可能立即开始发送数据而目的线程还未就绪导致数据丢失或信用机制紊乱。在复杂的系统初始化中仔细规划各个PSI-L数据流的启用顺序是避免启动期混乱的关键。6. 事件传输通道PSI-L的实时信号网络除了主要的数据包传输接口PSI-L还提供了一个独立的、低延迟的事件传输通道称为事件传输通道。这是一个与主数据流并行、但完全独立的子接口。6.1 ETL的工作原理与价值ETL的设计目标非常明确传输简单的、对时间敏感的事件信号例如中断请求、同步信号、DMA触发信号、定时器事件等。这些信号的特点是数据量极小通常就是一个比特或一个短整型但要求极低的传输延迟和确定的时序。独立性与简单性ETL独立于PSI-L上的任何数据包或消息传输。它使用一个简单的请求-就绪硬件握手协议每个时钟周期在每个事件通道上最多可以传输一个事件。这意味着事件传输几乎不占用主数据通道的带宽并且延迟是可预测的、极低的通常是一个或几个时钟周期。多通道一个PSI-L链路上可以有一个或多个ETL子接口每个都可以看作一个独立的事件通道用于传输不同类型的事件。6.2 ETL的配置与应用示例在手册的寄存器描述中我们看到了DMASS0_PSILSS_0_EVENT寄存器。这个寄存器很可能用于生成或控制通过ETL发送的事件。EVT字段15:0位可能就是写入要发送的事件值。例如在一个图像处理流水线中前一级的ISP图像信号处理器完成一帧图像的处理后需要通过PSI-L将图像数据发送给后级的VPU视频处理单元。同时ISP还需要一个非常及时的信号来通知VPU“新帧数据已就绪可以开始处理了”。这个通知信号就非常适合通过ETL来发送。ISP在发送完图像数据的最后一个PSI-L数据包后立即向它的ETL接口写入一个特定的事件值比如0x0001表示“帧就绪”。这个事件值通过ETL通道在一个或两个时钟周期内到达VPU的ETL接收端。VPU的硬件或固件检测到这个事件立即触发其内部的处理流程开始消费刚刚接收到的图像数据。通过这种方式数据搬运大流量、高带宽和流程控制小流量、低延迟被分离开来各自使用最适合的通道实现了效率和实时性的最佳平衡。在调试时你也可以利用ETL来传递一些关键的状态标记或性能计数信号用于系统级的性能剖析和监控。7. 实战中的挑战与排错指南在实际项目中使用PSI-L时你几乎一定会遇到配置错误、通信失败或性能不达预期的问题。下面是我总结的一些常见坑点和排查思路。7.1 常见问题与排查清单问题现象可能原因排查步骤与解决方法配置事务超时1. 目标线程ID错误。2. 目标线程模块未上电或处于复位状态。3. PSI-L配置代理访问路径存在硬件问题。1. 检查PROXY_THREAD_ID是否正确对照官方线程映射表。2. 确认目标模块的电源、时钟、复位状态已正确初始化。3. 检查PSIL_TO寄存器的超时周期设置是否合理太短可能误报。4. 尝试访问一个已知存在的、简单的线程如版本寄存器来测试配置通路。数据流无法启动1. 线程未正确配对。2. 线程未启用。3. 信用机制未建立接收方缓冲区未就绪。1. 使用配置代理读取源线程和目的线程的配对寄存器确认ID匹配。2. 检查双方的“启用”位是否已设置。3. 确认目的线程已正确报告其缓冲区深度源线程的信用计数器非零。对于简单测试可以在目的端设置一个大的缓冲区并确保已初始化。数据传输丢数或卡死1. 信用用尽流控生效。2. 发送速率超过接收方处理能力。3. 数据包格式或类型标识符错误。4. 仲裁优先级设置不当低优先级线程被饿死。1.这是最常见的原因。检查源线程的信用计数。如果为0说明接收方缓冲区满发送被阻塞。需要优化接收方处理速度或增加缓冲区。2. 在发送端加入流量控制逻辑或使用PSI-L内置的基于信用的流控。3. 核对数据相位类型标识符是否符合接收线程的预期。例如DMA数据线程期望收到Payload Data类型。4. 检查线程的优先级配置。确保高实时性线程被赋予高优先级同时避免低优先级线程完全得不到服务。性能低于预期1. 多个高优先级线程竞争同一链路仲裁开销大。2. 数据包太小协议开销占比高。3. 信用数量设置过小导致发送频繁等待信用归还。1. 分析数据流将非实时性要求的线程分配到不同的物理PSI-L链路上如果支持。2. 尽量聚合小数据包以更大的数据块进行传输提高有效数据占比。3. 在接收方资源允许的情况下适当增加其报告的缓冲区深度这会增加初始信用数允许发送方进行更长时间的突发传输。ETL事件丢失1. ETL通道未启用或配置错误。2. 事件产生频率超过ETL通道的带宽每个周期一个事件。3. 接收方未及时读取事件导致溢出。1. 检查PSILSS模块中与ETL相关的配置寄存器如EVENT,LINK寄存器。2. 确保事件产生频率不超过时钟频率。对于高频事件考虑使用计数器或仅在状态变化时发送。3. 在接收端实现一个足够深的事件FIFO并确保有后台任务或中断及时处理。7.2 调试技巧与心得充分利用状态寄存器像DMASS0_PSILSS_0_LINK和_DOWN这类寄存器反映了端点链路的状态。在初始化后和出问题时首先读取这些寄存器确保所有预期的链路都是“UP”状态。模拟与监控如果芯片支持使用仿真器或芯片内部的追踪模块来监控PSI-L链路上的实际流量。观察数据相位、线程ID、信用变化和仲裁情况这是定位复杂问题的终极手段。从简单到复杂不要一开始就搭建复杂的数据流。先配置一个最简单的、点对点的线程对用循环模式发送固定的测试数据确保底层通路是通的。然后再逐步增加线程数量、引入仲裁和流控。理解“数据就绪”信号PSI-L的发送端何时认为“数据就绪”这通常取决于前端模块如PDMA的状态。确保你正确触发了DMA或数据生产模块。很多时候通信失败问题不在PSI-L本身而在前端模块没有正确产生数据。时钟与复位域PSI-L两端的模块可能位于不同的时钟域或复位域。确保在配置和启动PSI-L通信之前相关时钟已经稳定复位已经释放。跨时钟域的信号需要同步处理虽然硬件可能已经处理但在软件初始化顺序上要留意。PSI-L协议是现代高性能SoC内部数据流设计的典范。它将复杂的互连问题抽象为清晰的线程模型通过信用流控和智能仲裁在提供高带宽的同时保证了确定性和公平性。掌握它意味着你能够更深入地理解和驾驭芯片内部的数据洪流设计出更高效、更可靠的嵌入式系统。当你下次阅读芯片手册看到那些错综复杂的数据路径图时尝试用“线程”和“PSI-L”的视角去解读很多问题都会豁然开朗。

相关新闻

最新新闻

日新闻

周新闻

月新闻