10. Introduction to TLM-2.0
第10章.TLM-2.0的介绍

10.1 Background
10.1 背景

The TLM-1 standard defined a set of core interfaces for transporting transactions by value or const reference. 
TLM-1 标准曾经定义了一组核心接口,用于传输事务的值或常量引用。
This set of interfaces is being used successfully in some applications, but it has three shortcomings with respect to the modeling of memory-mapped buses and other on-chip communication networks:
这组接口正在一些应用中被成功地使用着,但当它用在对内存映射的总线系统建模或用于其他片上通信网络建模时,它表现出3个不足之处。

a) TLM-1 has no standard transaction class, so each application has to create its own non-standard classes, resulting 
in very poor interoperability between models from different sources. 
TLM-1没有定义标准的事务类,所以,每个应用程序不得不创建它自己的非标准的类,导致了不同来源的模型之间非常差的互操作性。

TLM-2.0 addresses this shortcoming with the generic payload.
TLM-2.0设法用通用有效载荷解决了这个不足。

b) TLM-1 has no explicit support for timing annotation, so no standardized way of communicatingtiming information between models. 
TLM-1 没有显式地支持时间标注,所以,模型之间的通信信息没有标准化的路径。
TLM-2.0 addresses this shortcoming with the addition of timing annotation function arguments to the blocking and non-blocking transport interface.
TLM-2.0 解决这个问题的方法是在阻塞和非阻塞传输接口中添加了时间标注功能的参数。

c) The TLM-1 interfaces require all transaction objects and data to be passed by value or const reference, which may slow down simulation in certain use cases (although not all). 
TLM-1接口要求全部事务对象和数据通过值或常量引用进行传递,这在有些特定情况下会降低仿真速度(虽然不是全部)。
TLM-2.0 passes transaction objects by non-const reference, which is a fast solution for modeling memory-mapped buses.
TLM-2.0 传递事务对象是通过非常量引用,这是一个对内存映射总线系统建模的快速方案。

10.2 Transaction-level modeling, use cases, and abstraction
事务层建模,用例,和抽象

There has been a longstanding discussion in the ESL community concerning what is the most appropriate taxonomy of abstraction levels for transaction-level modeling. 
在ESL社区中存在一个长期的讨论,关于什么对事务层建模的抽象层级的最合适的分类法。

Models have been categorized according to a range of criteria, including granularity of time, frequency of model evaluation, functional abstraction, communication abstraction, and use cases. 
模型曾经被按照一系列的标准被分类,这些标准包括,时间粒度,模型评估频率,功能的抽象,通信的抽象,和用例。

The TLM-2.0 activity explicitly recognizes the existence of a variety of use cases for transaction-level modeling, but rather than defining an abstraction level around each use case, TLM-2.0 takes the approach of distinguishing between interfaces (APIs), on the one hand, and coding styles, on the other. 
TLM-2.0活动,明确地承认,在事务层建模中,这里有各种各样的用例;而不是为每一种用例定义一种抽象层。TLM-2.0一方面在接口之间进行区分,另一方面表现在编码风格上。

The TLM-2.0 standard defines a set of interfaces that should be thought of as low-level programming mechanisms for implementing transaction-level models, and then describes a number of coding styles that are appropriate for, 
but not locked to, the various use cases (Figure 17).
TLM-2.0 标准定义了一组接口,这些接口应该认为是用来实现事务层建模的底层的编程机制,并且同时给出了一些适用于不同用例的编程风格(但也不是非常绝对),见图17。

The definitions of the standard TLM-2.0 interfaces stand apart from the descriptions of the coding styles. 
标准的TLM-2.0 的接口的定义,与编程风格的说明是分开的。

It is the TLM-2.0 interfaces that form the normative part of the standard and ensure interoperability.
TLM-2.0的接口形成了该标准的规范部分,并且确保了互操作性。
 
Each coding style can support a range of abstraction across functionality, timing, and communication. 
每一种编程风格能够支持一系列的抽象,贯穿功能、时序和通信。

In principle users can create their own coding styles.
一般而言,用户能够创造出他们自己的编程风格。

An untimed functional model consisting of a single software thread can be written as a C function or as a single SystemC process, 
and it is sometimes termed an algorithmic model. 
包含一个单独的软件线程的非时序的功能模型,可以写成一个C函数,或者一个单独的SystemC进程,并且它有时被称为算法模型。

Such a model is not transaction level per se, because by definition a transaction is an abstraction of communication, and a single-threaded model has no inter-process communication. 
这样的一个模型本身并不是事务层的,因为根据定义,一个事务是一个通信的抽象,并且一个单独的线程模型并不存在进程间通信。

A transaction-level model requires multiple SystemC processes to simulate concurrent execution and communication.
一个事务层模型需要多个SystemC京城来仿真并行执行和通信。

An abstract transaction-level model containing multiple processes (multiple software threads) requires some
mechanism by which those threads can yield control to one another. 
一个包含多个进程(多个软件线程)的事务层模型,需要一些机制,以便这些线程能够互相让渡控制权。

This is because SystemC uses a cooperative multitasking model where an executing process cannot be pre-empted by any other process.
这是因为SystemC使用了一个合作的多任务模型,在这个模型中,一个执行种的进程并不能被任何其他进程抢占。

SystemC processes yield control by calling wait in the case of a thread process, or returning to the kernel in the case of a method process. 
SystemC的进程调用wait函数,当调用者是线程(thread)时,线程将让渡控制权;当调用者是方法(method)时,控制返回内核。

Calls to wait are usually hidden behind a programming interface (API), which may model a particular abstract or concrete protocol that may or may not rely on timing information.
对wait的调用,通常隐藏在一个可编程的接口后面,这可能是在对于给抽象的或具体的协议建模,这个协议可能是或者不是对时间信息有依赖的。

Synchronization may be strong in the sense that the sequence of communication events is precisely determined in advance, 
or weak in the sense that the sequence of communication events is partially determined by the detailed timing of the individual processes.
同步可能是强需求,当通信事件的顺序是事先精确决定的情境中;而当通信事件的顺序只是部分地被一些独立的进程的详细的时序所决定时,同步可能时弱需求。

Strong sychronization is easily implemented in SystemC using FIFOs or semaphores, allowing a completely untimed modeling style where in principle simulation can run without advancing simulation time. 
强同步,在SystemC中可以使用FIFOs或者semaphore来容易实现,这允许一个完全不计时的建模风格,这种情况下,仿真大体上可以不用紧随仿真时间而单独跑起来。

Untimed modeling in this sense is outside the scope of TLM-2.0. 
在这种情境下的不计时建模,是在TLM-2.0的视野之外的。
On the other hand, a fast virtual platform model allowing multiple embedded software threads  to run in parallel may use either strong or weak synchronization. 
另一方面,一个快速的虚拟平台模型允许多个嵌入式的软件线程并行地执行,则可能使用强的或弱的同步。

In this standard, the appropriate coding style for such a model is termed loosely-timed.
在本标准中,对这样的一个模型,适当的编程风格用专业术语表达为松散时间模型。

A more detailed transaction-level model may need to associate multiple protocol-specific timing points with each transaction, 
such as timing points to mark the start and the end of each phase of the protocol. 
一个更详细的事务层模型,可能是需要把特定协议里的多个定时点关联到事务上,例如用来标识协议中的每个相位的开始和结束的时间点。

By choosing an appropriate number of timing points, it is possible to model communication to a high degree of timing accuracy without the need to execute the component models on every single clock cycle. 
通过选择一堆合适的时间点,对一个通信过程做时间上的高精度建模是可能的,而且并不需要按照每一个时钟周期来精确地执行组件模型。

In this standard, such a coding style is termed approximately-timed.
在本标准中,这样的编程风格用专业术语表示为近似时间建模。

10.3 Coding styles
10.3 编程风格

A coding style is a set of programming language idioms that work well together, 
not a specific abstraction level or software programming interface. 
编程风格式一组编程语言的惯用语,它们组合在一起可以工作的很好,而不是指一个特别的抽象层或者软件编程接口。

For simplicity and clarity, this document restricts itself to elaborating two specific named coding styles: 
loosely-timed and approximately-timed. 
为了简单清晰起见,本文档将详细说明两个特别有名的编程风格:松散时间、近似时间。

By their nature the coding styles are not precisely defined, and the rules governing the TLM-2.0 core interfaces are defined
independently from these coding styles. 
就其本质而言,编程风格并不是精确定义的,而且,支配TLM-2.0的核心接口的那些规则是独立于编程风格的。

In principle, it would be possible to define other coding styles based on the TLM-1 and TLM-2.0 mechanisms.
原则上,基于TLM-1和TLM-2.0来定义其他的编程风格,是可能的。//LL::典型的,一句话里,中英文语义是倒叙的。

10.3.1 Untimed coding style
10.3.1 不定时编程风格

TLM-2.0 does not make explicit provision for an untimed coding style because all contemporary bus-based systems require some notion of time in order to model software running on one or more embedded processors. 
对于不定时编程风格,TLM-2.0没有做明确的规定,因为所有当代的基于总线的系统,需要一些时间概念,以便能够对于运行在一个或多个嵌入式处理器上软件进行建模。

However, untimed modeling is supported by the TLM-1 core interfaces. 
然而,不计时建模是由TLM-1核心接口支持的。
(The term untimed is sometimes used to refer to models that contain a limited amount of timing information of unspecified accuracy. 
In TLM-2.0, such models would be termed loosely-timed.)
术语“不定时的”有时候用来表示那些包含了一些有限的且不要求精确的时间信息的模型。在TLM-2.0中,这样的模型用专业术语称为时间松散的。

10.3.2 Loosely-timed coding style and temporal decoupling
10.3.2 松散时间编程风格 和 时间解耦

The loosely-timed coding style makes use of the blocking transport interface. 
松散时间编程风格,是利用阻塞传输接口实现的。

This interface allows only two timing points to be associated with each transaction, corresponding to the call to and return from the
blocking transport function. 
这个接口只允许两个定时点与一个事务相关联,分别对应阻塞传输函数的调用和返回。

In the case of the base protocol, the first timing point marks the beginning of the request, and the second marks the beginning of the response. 
在使用基础协议的时候,第一个时间点标记了事务请求的开始,而第二个时间点标记了事务应答的开始。

These two timing points could occur at the same simulation time or at different times.
这两个定时点,可能发生在相同的仿真时间点上,或者不同的时间点上。

The loosely-timed coding style is appropriate for the use case of software development using a virtual platform model of an MPSoC, where the software content may include one or more operating systems.
松散时间编程风格,适用于那些基于多处理器片上系统的虚拟平台模型的软件开发的用例中。

The loosely-timed coding style supports the modeling of timers and interrupts, sufficient to boot an operating system and run arbitrary code on the target machine.
松散时间编程风格支持对定时器和中断的建模,这足够启动一个操作系统并在目标机器上运行任意的代码。

The loosely-timed coding style also supports temporal decoupling, where individual SystemC processes are permitted to run ahead in a local “time warp” without actually advancing simulation time until they reach the
point when they need to synchronize with the rest of the system. 
松散时间编程风格也支持时间解耦,这时,在仿真时间并没有实际往前行进的情况下,那些单独的SystemC进程允许在自己的局部时间隧道里继续运行,直到这些进程运行到需要跟系统的其他部分进行同步时为止。

Temporal decoupling can result in very fast simulation for certain systems  because it increases the data and code locality and reduces the scheduling overhead of the simulator. 
时间解耦在某些系统里可以产生快速得仿真效果,因为它增加了数据和代码得位置,然后节省了仿真器得调度开销。

Each process is allowed to run for a certain time slice or quantum before switching to the next, or instead, it may yield control when it reaches an explicit synchronization point.
每个进程允许跑满一个特定得时间片或者量子时间,然后再切换到下一个进程;或者,进程会在运行到一个显式的同步点时让渡CPU的控制权。

Just considering SystemC itself, the SystemC scheduler keeps a tight hold on simulation time. 
仅仅考虑SystemC自身,SystemC的调度器对仿真时间有非常紧密的把控。

The scheduler advances simulation time to the time of the next event; then it runs any processes due to run at that time or sensitive to that event.
调度器把仿真器的时间从当前事件推进到下一个事件;这时,仿真器可以运行任何一些到此时可以运行的和对下一个事件敏感的进程。

SystemC processes only run at the current simulation time (as obtained by calling the method sc_time_stamp), and whenever a SystemC process reads or writes a variable, it accesses the state of the variable as it would be at the current simulation time. 
SystemC 进程只运行在当前仿真时间下(就是用sc_time_stamp方法获得的当前时间),
并且,无论何时,一个SystemC进程访问一个变量,它访问到的,都是这个变量在当前仿真时间点上的状态。

When a process finishes running, it must pass control back to the simulation kernel. 
当一个进程完成运行,它必须把控制权归还给仿真器内核。

If the simulation model is written at a fine-grained level, then the overhead of event scheduling and process context switching becomes the dominant factor in simulation speed. 
如果一个仿真模型是在细粒度层编写的,那么事件调度和进程上下文的切换的总开销就变成了影响仿真速度的主要因素。

One way to speed up simulation is to allow processes to run ahead of the current simulation time, or temporal decoupling.
有一个可以加速仿真的方法,就是允许进程可以泡在当前仿真时间的前面,或者说是时间解耦。

When implementing temporal decoupling in SystemC, a process can be allowed to run ahead of simulation time until it needs to interact with another process, for example, to read or update a variable belonging to another process. 
当在SystemC中实现时间解耦时,一个进程能够跑在当前仿真时间之前,直到它需要跟其他进程互动,这种互动可以是去访问属于另一个进程的变量。

At that point, the process may either access the current value and continue (with some possible loss of timing accuracy)  or may return control to the simulation kernel, only resuming the process when simulation time has caught up with the local “time warp.” 
在那时,这个进程既可以访问这个变量的当前值(会伴随一些时间精度的可能损失)或者,进程可以把运行控制权归还给仿真器内核,等到当前仿真时间追赶上局部“时间隧道”时再恢复进程运行。

Each process is responsible for determining whether it can run ahead of simulation time without breaking the functionality of the model. 
在不破坏模型功能的前提下,每一个进程自己负责决定是否要跑在当前仿真时间之前。

When a process encounters an external dependency, it has two choices: Either force synchronization, which means yielding to allow all other processes to run as normal until simulation time catches up,  or sample or update the current value and continue. 
当进程遇到一个外部依赖时,它有两个选择:要么强制同步,这意味着让步给其他所有进程正常去运行,直到仿真时间赶上来;
要么访问当前值,并继续运行。

The synchronization option guarantees functional congruency with the standard SystemC simulation semantics. 
采用同步选项,会保证与标准的SystemC仿真语义的功能一致性。

Continuing with the current value relies on making assumptions concerning communication and timing in the modeled system. 
用当前值继续运行,依赖于所建模系统的通信和计时方面所做的假设。

It assumes that no damage will be done by sampling or updating the value too early or too late. 
假设之这样的,当过早或过晚访问变量的值并不会造成损害。

This assumption is usually valid in the context of a virtual platform simulation, where the software stack should not be dependent on the low-level details of the hardware timing anyway.
在仿真一个虚拟的上下文中,这个假设通常是合法的;这种情形中,软件栈应该不会对硬件计时的底层细节有任何依赖。

Temporal decoupling is characteristic of the loosely-timed coding style.
时间解耦是松散时间编程风格的特性。

If a process were permitted to run ahead of simulation time with no limit, the SystemC scheduler would be unable to operate and other processes would never get the chance to execute. 
不好玩的情况,如果进程被允许毫无限制地跑到仿真时间前去,那么SysteC调度器会无法运行,并且其他的进程会得不到运行的机会。

This may be avoided by reference to the global quantum, which imposes an upper limit  on the time a process is allowed to run ahead of simulation time. 
这个问题可以通过引用全局量子时间来避免,它在一个进程所允许跑到当前仿真时间之前的时间上强加了一个上限。

The quantum is set by the application, and the quantum value represents a trade-off between simulation speed and accuracy. 
量子时间有应用程序设置,而且量子时间表现了在仿真速度和精度之间的权衡。

Too small a quantum forces processes to yield and synchronize very frequently, slowing down simulation. 
太小的量子时间会强制进程让出和同步非常频繁,也就降低了仿真速度。

Too large a quantum might introduce timing inconsistencies across the system, possibly to the point where the system ceases to function.
太大的量子时间可能会引进系统中计时的不一致性,或者贯穿整个系统,或者直到系统停止运行。

For example, consider the simulation of a system consisting of a processor, a memory, a timer, and some slow external peripherals. 
例如,考虑有一个处理器、一个内存、一个时钟、和一些慢速外部外设构成的系统的仿真。

The software running on the processor spends most of its time fetching and executing instructions from system memory, 
and only interacts with the rest of the system when it is interrupted by the timer, say every 1 ms. 
运行在这个处理器上的软件,花费了绝大部分时间从内存中取指令和运行指令,并且尽在被时钟中断时,软件才与系统的其他部分互动,我们假设时钟周期是1ms。

The ISS that models the processor could be permitted to run ahead of SystemC simulation time with a quantum of up to 1 ms, 
making direct accesses to the memory model, but only synchronizing with the peripheral models at the rate of timer interrupts. 
处理器模型可以允许跑到SystemC仿真时间的前边多达1ms的量子时间,这期间它可以直接访问内存模型,但是,它仅按照时钟中断发生的速度与外设模型同步。

The point here is that the ISS does not have to be locked to the simulation time clock of the hardware part of the system, as would be the case with more traditional hardware-software co-simulation.
这里要说的是,处理器模型不用非要锁定在系统硬件部分的仿真时间的时钟上,就非要像的硬件-软件 共同仿真的更传统的情形那样子。
 
Depending on the detail of the models, temporal decoupling alone could give a simulation speed improvement of approximately 10X, or 100X, when combined with DMI.
具体依赖于模型的细节,时间解耦仅仅能够给仿真速度提高十多倍,或一百多倍,而且要结合DMI一起。

It is quite possible for some processes to be temporally decoupled and others not, and for different processes to use different values for the time quantum. 
对一些进程做时间解耦,而另一些进程不做时间解耦,而且不同的进程可以使用不同的长短的时间量子。

However, any process that is not temporally decoupled is likely to become a simulation speed bottleneck.
然而,任何未作时间解耦的进程,很可能变成仿真速度的一个瓶颈。

In TLM-2.0, temporal decoupling is supported by the tlm_global_quantum class and the timing annotation of the blocking and non-blocking transport interface. 
在TLM-2.0中,使用tlm_global_quantum 类和 在阻塞与非阻塞传输中的计时标注来支持时间解耦。

The utility class tlm_quantumkeeper provides a convenient way to access the global quantum.
工具类tlm_quantumkeeper 提供了访问全局量子的便利方式。

10.3.3 Synchronization in loosely-timed models
10.3.3 松散时间模型中的同步

An untimed model relies on the presence of explicit synchronization points (that is calls to wait or blocking method calls) 
in order to pass control between initiators at predetermined points during execution. 
一个不计时模型依赖明确的同步点(也就是调用wait和阻塞方法),以便在预先决定的执行期间的一些时间点上,在发起者之间传递控制权

A loosely-timed model can also benefit from explicit synchronization in order to guarantee deterministic execution, 
but a loosely-timed model is able to make progress even in the absence of explicit synchronization points (calls to wait), 
because each initiator will only run ahead as far as the end of the time quantum before yielding control. 
一个时间松散的模型也能从明确的同步获益,以便保证确定的执行;但是一个松散时间模型,在没有使用明确的同步(调用wait)时,也能运行向前进,
因为没有给发起者将只能在它让出控制权之前向前运行最远一个时间量子。

A loosely-timed model can increase its timing accuracy by using synchronizationon-demand, that is, 
yielding control to the scheduler before reaching the end of the time quantum.
松散时间模型可以通过使用同步命令来增加它的计时精度,也就是说,在跑完量子时间之前就让出控制权给调度器

The time quantum mechanism is not intended to ensure correct system synchronization, but it is a simulation mechanism that allows multiple system initiators to make progress in a scheduler-based simulation environment. 
时间量子机制,不是设计来保证正确的系统同步,但是它的设计目的是允许多个系统中的发起者,在一个基于调度器的仿真环境中,都能运行向前进,

The time quantum mechanism is not an alternative to designing an explicit synchronization scheme at the system level.
反过来,时间量子机制不是设计明确的系统级同步机制的可选方式。

10.3.4 Approximately-timed coding style
10.3.4 近似时间编程风格

The approximately-timed coding style is supported by the non-blocking transport interface, which is appropriate for the use cases of architectural exploration and performance analysis. 
近似时间编程风格是由非阻塞传输接口支持的,他适合用于体系结构探索和性能分析。

The non-blocking transport interface provides for timing annotation and for multiple phases and timing points during the
lifetime of a transaction.
非阻塞传输接口,在事务的整个生命周期中,提供时间标注和多相位和计时点

For approximately-timed modeling, a transaction is broken down into multiple phases, with an explicit timing point marking the transition between phases. 
在近似时间建模中,一个事务被分解成多个相位,在相位之间用明确的计时点标识这个事务。

In the case of the base protocol there are exactly four timing points marking the beginning and the end of the request 
and the beginning and the end of the response. 
在请求的开始与结束之间,以及在应答的开始与结束之间,当使用基础协议的情形中,这里有4个定时点来标识事务。

Specific protocols may need to add further timing points, which may possibly cause the loss of direct compatibility with the generic payload.
那些特别的协议中,可能需要增加更多的计时点,这可能导致通用有效载荷的直接兼容性的丧失。

Although it is possible to use the non-blocking transport interface with just two phases to indicate the start and end of a transaction, the blocking transport interface is generally preferred for loosely-timed modeling.
虽然在非阻塞传输接口中使用两个相位来指示一个事务的开始和结束是可能的,但是阻塞传输接口通常被用来做松散时间建模。

The approximately-timed coding style cannot generally exploit temporal decoupling because of the need for timing accuracy. 
在近似时间编程风格中,一般不能利用时间解耦,因为近似时间模型需要计时的精确性。

Instead, each process typically executes in lock step with the SystemC scheduler. 
而是,每个进程都是踩着SystemC调度器的时钟步伐典型地执行。

Process interactions are annotated with specific delays. 
进程的互动用详细的延迟来标注。

To create an approximately-timed model, it is generally sufficient to annotate delays representing the data transfer times 
for write and read commands and the latency of the target. 
为了创建一个近似时间模型,使用延迟标注来表示读写数据的时间和目标设备内部的延迟时间,这通常是足够的。

For the base protocol, the data transfer times are effectively the same as the minimum initiation interval  or accept delay between two successive requests or two successive responses. 
对于基础协议,数据的传输时间实际上与最小的初始化间隔,或者两个连续的请求(或应答)之间的接受延迟是一样。

The annotated delays are implemented by making calls to the SystemC scheduler, that is, wait(delay) or notify(delay).
标注的延迟是通过调用回SystemC调度器来实现的,也就是,wait(delay)或者notify(delay).

10.3.5 Characterization of loosely-timed and approximately-timed coding styles
松散时间和近似时间编程风格的特性

The coding styles can be characterized in terms of timing points and temporal decoupling.
可以使用计时点和时间解耦分别作为编程风格的特性。

Loosely-timed.     Each transaction has just two timing points, marking the start and the end of the transaction. 
Simulation time is used, but processes may be temporally decoupled from simulation time. 
松散时间.   每一个事务仅有两个计时点,用来标识事物的开始和结束。仿真时间还是要用到的,但是进程可以从仿真时间解耦出来。
Each process keeps a tally of how far it has run ahead of simulation time, and it may yield because it reaches an explicit
synchronization point or because it has consumed its time quantum.
每个进程都有一个账本记录自己已经超过仿真时间多远了,并且它可能让出控制权,因为它已经到达了一个显式的同步点或者它已经耗尽它自己的时间量子。

Approximately-timed.   Each transaction has multiple timing points. 
近似时间.  每个事务拥有多个计时点。
Processes typically need to run in lock step with SystemC simulation time. 
典型的,进程都需要跟着SystemC的仿真时间的时钟脚步运行。
Delays annotated onto process interactions are implemented using timeouts (wait) or timed event notifications.
标注在进程互动上的延迟,是用超时(wait函数)或者计时事件通知来实现的。

Untimed.    The notion of simulation time is unnecessary. Processes yield at explicit pre-determined synchronization points.
不计时.   仿真时间的概念就是多余的了。进程在显式的预先确定的同步点让出控制权。

10.3.6 Switching between loosely-timed and approximately-timed modeling
松散时间和近似时间建模过程的切换

A model may switch between the loosely-timed and approximately-timed coding style during simulation.
在仿真期间,一个模型可能会在松散时间和近似时间编程风格之间切换。

The idea is to run rapidly through the reset and boot sequence at the loosely-timed level, then switch to
approximately-timed modeling for more detailed analysis once the simulation has reached an interesting stage.
整体思路是这样的,在重置和启动序列里,在松散时间层级上快速运行,然后,一旦仿真已经运行到了感兴趣的阶段,就切换到近似时间模型中做更加详细的分析。

10.3.7 Cycle-accurate modeling

10.3.7 周期精确的建模方法
Cycle-accurate modeling is beyond the scope of TLM-2.0 at present. 
周期精确的建模方法超出了TLM-2.0当前的关注范围。

It is possible to create cycle-accurate models using SystemC and TLM-1 as it stands, but the requirement for the tandardization of a cycle accurate coding style remains an open issue,  possibly to be addressed by a future Accellera Systems Initiative standard.
按照实际情况来说,使用SystemC和TLM-1创建周期精确模型是可能的,但是对创建周期精确的编程风格的标准化需求,是一个开放的事情;可能会在进一步的ASI规范中解决掉。

In principle only, the approximately-timed coding style might be extended to encompass cycle-accurate modeling by defining an appropriate set of phases and rules. The TLM-2.0 release includes sufficient machinery for this, but the details have not been worked out.
仅在原则上来说,近似时间编程风格可以被扩展来完成周期精确建模,这需要定义一组适当的相位和规则。TLM-2.0的发行版包含了足够的设施来支持这么做,但是详细的设计还没有完成。

10.3.8 Blocking versus non-blocking transport interfaces
10.3.8 阻塞与非阻塞传输接口的对比

The blocking and non-blocking transport interfaces are distinct interfaces that exist in TLM-2.0 to support different levels of timing detail. 
阻塞和非阻塞接口是TLM-2.0中有明显不同的两个接口,分别用于支持不同层级的计时。

The blocking transport interface is only able to model the start and end of a transaction, with the transaction being completed within a single function call. 
阻塞传输接口仅能够对一个事务的开始和结束进行建模,这个事务会在一次单独的调用中完成生命周期。

The non-blocking transport interface allows a transaction to be broken down into multiple timing points, and typically requires multiple function calls for a single transaction.
非阻塞传输接口允许要给事务被分解成多个计时点,而且典型的情况下,需要多次函数调用来完成一个单独的事务的生命周期。

For interoperability, the blocking and non-blocking transport interfaces are combined into a single interface.
为了支持互操作性,阻塞和非阻塞接口被合进一个单独的接口。

A model that initiates transactions may use the blocking or non-blocking transport interfaces (or both) according to coding style. 
一个初始化事务的模型可以根据编程风格,使用阻塞和非阻塞传输接口中的一个或两个。

Any model that provides a TLM-2.0 transport interface is obliged to provide both the blocking and non-blocking forms for maximal interoperability, although such a model is not obliged to implement both interfaces internally.
提供了TLM-2.0传输接口的任何模型,必须提供阻塞和非阻塞的形式来支持最大化的互操作性,虽然这样的一个模型不用非要在内部实现这两个接口。

TLM-2.0 provides a mechanism (the so-called convenience socket) to automatically convert incoming blocking or non-blocking transport calls to non-blocking or blocking transport calls, respectively.
TLM-2.0提供了一种机制(被称作便利套接字)来自动把阻塞或非阻塞传输调用,分别变换成为非阻塞和阻塞传输调用。

Converting transport call types does incur some cost, particularly converting an incoming non-blocking call to a blocking implementation. 
变换传输调用的类型会引起一些开销,特别是把一个到来的非阻塞传输调用变换为阻塞传输调用。

However, the cost overhead is mitigated by the fact  that the presence of an approximately-timed model is likely to have a negative impact on simulation speed anyway.
然而,这个经常性的支出被减轻了,因为一个近似时间模型的参与,很可能对仿真速度产生负面的影响。

The C++ static typing rules enforce the implementation of both interfaces, but an initiator can choose dynamically whether to call the blocking or the non-blocking transport method. 
C++的静态类型规则强制两种类型的接口都要实现,但是,一个发起者能够动态选择是否调用阻塞或非阻塞传输方法。

It is possible for different initiators to call different methods, or for a given initiator to switch between blocking and non-blocking calls on-the-fly. 
不同的发起者可能调用不同的方法,或者对于一个特定的发起者在运行的时候可以在两种接口之间切换调用。

This standard includes rules governing the mixing and ordering of blocking and non-blocking transport calls to the same target.
本标准包括了一组规则来管理那些针对同一个目标设备的混合的和有序的阻塞与非阻塞传输调用。

The strength of the blocking transport interface is that it allows a simplified coding style for models that are able to complete a transaction in a single function call. 
阻塞传输接口的长处是它能够简化一类模型的编程风格,就是那些能够在一次单独的函数调用中完成一个事务的模型。

The strength of the non-blocking transport interface is that it supports the association of multiple timing points with a single transaction. 
而非阻塞传输接口的长处是它支持把一个单独的事务跟多个计时点关联起来。

In principle, either interface supports temporal decoupling, but the speed benefits of temporal decoupling are likely to be
nullified by the presence of multiple timing points for approximately-timed models.
原则上,任何一类接口都支持时间解耦,但是,对于近似时间模型,多个计时点的出现可能会取消掉时间解耦带来的速度获益。

10.3.9 Use cases and coding styles
10.3.9 用例和编程风格

Table 52 summarizes the mapping between use cases for transaction-level modeling and coding styles:
表格52  总结了传输层级建模的用例与编程风格之间的联系。

10.4 Initiators, targets, sockets, and transaction bridges

The TLM-2.0 core interfaces pass transactions between initiators and targets (Figure 18).
TLM-2 的核心接口函数,在发起者与目标之间传递事务(如图18)

An initiator is a module that can initiate transactions, that is, create new transaction objects and pass them on by calling a method of one of the core interfaces. 
一个发起者,是一个可以初始化事务的模块,也就是说,能够创建新的事务对象并且通过调用TLM2核心接口中的一个方法把这些事务对象传递出去。

A target is a module that acts as the final destination for a transaction.
一个目标,是一个扮演一个事务的最终目的地的模块。

In the case of a write transaction, an initiator (such as a processor) writes data to a target (such as a memory).
在一个写事务的情景中,一个发起者(例如一个处理器)写数据到一个目标(例如一个存储器)。

In the case of a read transaction, an initiator reads data from a target. 
在一个读事务的情境中,一个发起者从目标读数据。

An interconnect component is a module that accesses a transaction but does not act as an initiator or a target for that transaction, typical examples being arbiters and routers. 
一个互联组件,是一个要访问一个事务的的模块,但它既不充当发起者也不充当目标,典型的例子是仲裁器和路由器。

The roles of initiator, interconnect, and target can change dynamically. 
发起者、互联组件和目标,能够动态改变。

For example, a given component may act as an interconnect for some transactions but as a target for other transactions.
例如,一个给定的组件,对于某些事务它可以充当一个互联组件,而对于其他事务它会充当一个目标。

To illustrate the idea, this paragraph will describe the lifetime of a typical transaction object (Figure 19). 
为了举例说明这个想法,本段将会描述一个典型的事务对象的生命周期(如图19)。

The transaction object is created by an initiator and passed as an argument of a method of the transport interface (blocking or non-blocking). 
这个事务对象被发起者创建,并且作为阻塞或非阻塞传输接口的一个方法的参数被传递出去。

That method is implemented by an interconnect component such as an arbiter, which may read attributes of the transaction object before passing it on to a further transport call. 
这个方法被一个例如像仲裁器一样的互联组件实现,在通过进一步的方法调用把事务传输下去之前,传输这个事务对象的互联组件实现的方法有可能会读取事务对象的属性值。

That second transport method is implemented by a second interconnect component, such as a router, which in turn passes on the transaction through a third transport call to a target such as a memory, the final destination for the transaction object. 
第二个传输方法在第二个互联组件中实现,例如一个路由器,然后轮到它通过第三个传输调用把事务传递到一个目标,例如一个存储器,也就是这个事务对象的最后目的地。

(The actual number of interconnect components will vary from transaction to transaction. There may be none.) 
(实际的互联组件的个数将会随事务的不同而不同,这里也可能没有互联组件。)

This sequence of method calls is known as the forward path. 
这个方法调用的顺序就是众所周知的前向路径。

The transaction is executed in the target, and the transaction object may be returned to the initiator  in one of two ways, either carried with the return from the transport method calls as they unwind, known as the return path, or passed by making explicit transport method calls on the opposite path from target back to initiator, known as the backward path. 
这个事务会在目标中被执行,而且这个事务对象可能通过两条路劲之一返回给发起者;要么是从意义展开的传输方法返回这个事务,也就是众所周知的返回路径。要么是通过从目标到发起者这个相反的路径上显示地调用传输方法来传递这个事务对象,也就是众所周知的后向路径。

This choice is determined by the return value from the non-blocking transport method. 
这个选择是由从非阻塞传输方法中返回的值决定的。

(Strictly speaking there are two return paths corresponding to the forward and backward paths, but the meaning is usually clear from the context.)
严格地讲,这里有两条返回路径,分别对应着前向路径和后向路径,但是这些意义通常可以从上下文弄清楚。

========================分段线===========================

The forward path is the calling path by which an initiator or interconnect component makes interface method calls forward 
in the direction of another interconnect component or the target. 
前向路径是这样一个调用路径,通过它,一个发起者或者一个互联组件进行接口方法的向前调用,向着另一个互联组件或目标的方向。

The backward path is the calling path by which a target or interconnect component makes interface 
method calls back in the direction of another interconnect component or the initiator. 
后向路径是这样一个调用路径,通过它,一个目标或者一个互联组件进行接口方法的向后调用,向着另一个互联组件或发起者的方向。

The entire path between an initiator and a target consists of a number of hops, each hop connecting two adjacent components. 
在发起者到接收者之间的整条路经,由好几跳构成,每一跳连接2个相邻的组件。

A hop consists of one initiator socket bound to one target socket. 
一跳由一个绑定在目标套接字上的发起者套接字构成。
The number of hops from initiator to target is one greater than the number of interconnect components on that path. 
从发起者到目标的跳数,比这条路径上的互联组件个数多一。

When using the generic payload, the forward and backward paths should each pass through the same set of components and sockets in opposing directions.
当时用净核的时候,无论是前向路径还是后向路径,应该各自在相反的方向上通过同一组的组件和套接字。
In order to support both forward and backward paths, each connection between components requires a port and an export, both of which have to be bound. 
为了支持前向和后向路径,组件之间的任一连接必须要有一个port和一个export,而且这两者都是被绑定了的。
This is facilitated by the initiator socket and the target socket. 
这个要求,由系统开发的发起者套接字和目标套接字提供辅助。
An initiator socket provides a port for interface method calls on the forward path, and an export for interface method calls on the backward path. 
一个发起者套接字提供一个port,支持前向路径的接口方法调用,同时提供一个export支持后向路径的接口方法调用。
A target socket provides the opposite. (More specifically, an initiator socket is derived from class sc_port and has an sc_export,
 and vice versa for a target socket.) 
 一个目标套接字,则提供了相反的port和export。更确切地说,一个initiator_socket派生于一个sc_port类,并且拥有一个sc_export成员。
而一个目标套接字,则派生于一个sc_export ,并且拥有一个sc_port成员。

The initiator and target socket classes overload the SystemC port binding operator to bind implicitly both forward and backward paths.
发起者和目标套接字类都重载了SystemC port的绑定操作符,以便隐式地绑定前向和后向路径。
 As well as the transport interfaces, the sockets also encapsulate the DMI and debug transport interfaces (see below).
 如同这些传输接口,套接字也封装了DMI和debug传输接口(见后文)。

When using sockets, an initiator component will have at least one initiator socket, a target component at least one target socket, 
and an interconnect component at least one of each. 
当使用套接字时,一个发起者组件将至少拥有一个发起者套接字,一个目标组件将至少拥有一个目标套接字,而对于一个互联组件而言,每种套接字都至少拥有一个。

A component may have several sockets transporting different transaction types, 
in which case a single component may act as an initiator or as a target for multiple independent transactions.
一个组件可能由几个套接字,分别用来传输不同的事务类型,在这种情况下,对于多个独立的不同事务,单个组件可能充当一个发起者,也可能充当一个目标。

In order to model a bus bridge, there are two alternatives. 
为了对于给总线桥建模,这里有两个选择。

Either model the bus bridge as an interconnect component or model the bus bridge as a transaction bridge between 
two separate TLM-2.0 transactions. 
要么,把这个总线桥建模成一个互联组件,要么,把这个总线桥建模成两个独立的TLM-2.0事务之间的一个事务桥。

An interconnect component would pass on a pointer to a single transaction object, which is the best approach for simulation speed. 
一个发起者组件,应该传递一个指向单个事务对象的指针,这样子,是提高仿真速度的最好方法。

A transaction bridge would require the transaction object to be copied, which gives much
more flexibility because the two transactions could have different attributes.
一个事务桥,将会要求拷贝事务对象,这将给与更多的灵活性,因为这两个事务可以拥有不同的属性。

The use of TLM-2.0 sockets is recommended for maximal interoperability, convenience, and a consistent coding style. 
为了获得最大的互操作性、便利和一致的编码风格,我们隆重推荐使用TLM-2.0 套接字。

Although it is possible for components to use SystemC ports and exports directly with the TLM-2.0 core interfaces, this is not recommended.
虽然对于组件来说,直接使用使用SystemC的ports和exports 以及TLM-2.0核心接口是可能的,但是我们并不推荐。

10.5 DMI and debug transport interfaces
10.5 DMI和debug传输接口

The direct memory interface (DMI) and debug transport interface are specialized interfaces distinct from the transport interface, 
providing direct access and debug access to an area of memory owned by a target.
直接内存访问接口和调试传输接口是不同于事务传输接口的特殊接口,它提供对目标设备里的一块内存区域的直接访问和调试访问。

Once a DMI request has been granted, the DMI interface enables an initiator to bypass the usual path through the
interconnect components used by the transport interface.
一旦一个直接内存请求被授予,直接内存接口函数会使能一个发起者绕过事务传输接口通常走的内部互联组件构成的路径。

DMI is intended to accelerate regular memory transactions in a loosely-timed simulation, 
whereas the debug transport interface is for debug access free of the delays or side-effects associated with regular transactions.
DMI的设计意图是加速松散时间仿真时的常规的内存访问事务,然而,调试传输接口设计的意图为消除调试访问对常规事务延迟的影响和其他不正常影响。

The DMI has both forward (initiator-to-target) and backward (target-to-initiator) interfaces, 
whereas debug only has a forward interface (see 11.2 and 11.3).
DMI既有前向(发起者到目标)也有后向(目标到发起者)接口,而调试接口只有前向接口(见11.2和11.3)

10.6 Combined interfaces and sockets
10.6 结合接口和套接字

The blocking and non-blocking transport interfaces are combined with the DMI 
and debug transport interfaces in the standard initiator and target sockets. 
阻塞和非阻塞传输接口跟DMI和debug传输接口结合在一起,构成了标准的发起者和目标套接字。

All four interfaces (the two transport interfaces, DMI, and debug) can be used in parallel to access a given target 
(subject to the rules described in this standard).
这四类接口(nb、b、DMI、debug)可以并行地用来访问一个给定的目标设备(要服从本标准所描述的规则)。

These combined interfaces are one of the keys to ensuring interoperability between components using the TLM-2.0 standard, 
the other key being the generic payload (see 13.1).
这些组合在一起的接口,是使用TLM-2.0标准的组件之间保证互操作性的关键要素之一,其他的关键要素是通用载荷(见13.1)。

The standard target sockets provide all four interfaces, 
so each target component must effectively implement the methods of all four interfaces. 
标准的目标套接字提供全部四类接口,所以每一个目标组件必须有效实现这四类接口的全部方法。

However, the design of the blocking and non-blocking transport interfaces together with the provision of convenience sockets to convert 
between the two means that a given target need only implement either the blocking or the non-blocking transport method, 
not both, according to the speed and accuracy requirements of the model.
然而,把阻塞和非阻塞传输接口设计在一块,使得能够在一个目标中可以互相变换这两种方式,
这样,一个给定的目标只需要实现一个阻塞传输方法,或者只实现一个非阻塞传输方法,不用一起实现两者,这按照模型的仿真速度和仿真精度来决定。

A given initiator may choose to call methods through any or all of the core interfaces, 
again according to the speed and accuracy requirements. 
一个给定的发起者可以选择调用核心接口中的任意一个或全部的方法,还是这个原则,这按照模型的仿真速度和仿真精度来决定。

The coding styles mentioned above help guide the choice of an appropriate set of interface features. 
上述提到的编程风格帮助指导选择一组适当的接口特性。

Typically, a loosely-timed initiator will call blocking transport, DMI and debug, 
whereas an approximately-timed initiator will call non-blocking transport and debug.
典型的用法,一个松散时间发起者将会调用阻塞传输、DMI和debug接口,
一个近似时间接口发起者将会调用非阻塞传输接口和调试接口。

10.7 Namespaces
10.7 命名空间

The TLM-2.0 classes shall be declared in two top-level C++ namespaces, tlm and tlm_utils. 
TLM-2.0的类都在两个顶层的C++命名空间中声明,tlm和tlm_utils。

Particular implementations of the TLM-2.0 classes may choose to nest further namespaces within these two namespaces, 
but such nested namespaces shall not be used in applications.
关于TLM-2.0的类的独有的实现,可以选择把更多的命名空间嵌入这两个命名空间中,但是这些嵌入的命名空间不应当在应用程序中使用。

Namespace tlm contains the classes that comprise the interoperability interface for memory-mapped bus modeling.
tlm这个命名空间包含的类,构成了对内存映射总线建模的互操作性接口。

Namespace tlm_utils contains utility classes that are not strictly necessary for interoperability at the interface 
between memory-mapped bus models but that are nevertheless a proper part of the TLM-2.0 standard.
tlm_utils这个命名空间包含着工具类,这些工具类不是在支持基于内存映射总线模型之间的互操作性时所必须的,但是,尽管如此,它们依然是TLM-2.0中恰当的内容。

10.8 Header files and version numbers
10.8 头文件和版本号

Applications should #include the header file tlm, which shall contain all of the public declarations for the TLM-2.0 interoperability layer. 
应用程序应当包含tlm.h这个头文件,它应当包含了支持TLM-2.0互操作性层的所有的公共声明。

The header files tlm and tlm.h shall be equivalent in the sense that they shall include precisely the same set of declarations and macros, 
and they may be used interchangeably. 
头文件tlm和tlm.h应该是等价的,也就是说,它们应当包含完全相同宏和类的声明,而且它们应该可以互换使用。

The header file tlm.h is provided for backward compatibility with earlier versions of TLM-2.0 
and may be deprecated in future versions of this standard. 
头文件tlm.h是用来向后相容那些TLM-2.0的早期版本,而且在可能在本标准将来的版本中弃用。

The TLM-2.0 utilities shall not be present in the header files tlm or tlm.h. 
TLM-2.0的工具类不应当出现在头文件tlm或tlm.h中。

Applications should also explicitly #include the header files for any TLM-2.0 utilities they may wish to use, 
which shall be placed in a directory named tlm_utils. 
应用程序应该也显式地包含全部TLM-2.0工具类的头文件,当在应用程序中用到时,这些工具类应当放在一个名字为tlm_utils的文件夹中。

The precise file names for each of these header files are defined in their respective clauses in this standard.
这些头文件的确切文件名,在本标准里它们相应的章节中定义。

10.8.1 Software version information
10.8.1 软件版本信息

The header files tlm and tlm.h shall include a set of macros, constants, 
and functions that provide information concerning the version number of the TLM-2.0 software distribution. 
头文件tlm和tlm.h应该包括一组宏、常量和函数,它们提供了关于TLM-2.0的发布版的版本号。
Applications may use these macros and constants.
应用程序可以使用这些宏和常量。

The value of the macros and constants defined in this clause may be independent of the values of 
the corresponding set of definitions for SystemC given in 8.6.5.
本章中定义的宏和常量的值,可以与在8.6.5章中SystemC中定义的对应值是相互独立的。

10.8.2 Definitions
10.8.2 定义

namespace tlm
{
#define TLM_VERSION_MAJOR implementation-defined_number // For example, 2
#define TLM_VERSION_MINOR implementation-defined_number // 0
#define TLM_VERSION_PATCH implementation-defined_number // 1
#define TLM_VERSION_ORIGINATOR implementation-defined_string // "OSCI"
#define TLM_VERSION_RELEASE_DATE implementation-defined_date // "20090329"
#define TLM_VERSION_PRERELEASE implementation-defined_string // "beta"
#define TLM_IS_PRERELEASE implementation-defined_bool // 1
#define TLM_VERSION implementation-defined_string
// "2.0.1_beta-OSCI"
#define TLM_COPYRIGHT implementation-defined_string
const unsigned int tlm_version_major;
const unsigned int tlm_version_minor;
const unsigned int tlm_version_patch;
const std::string tlm_version_originator;
const std::string tlm_version_release_date;
const std::string tlm_version_prerelease;
const bool tlm_is_prerelease;
const std::string tlm_version_string;
const std::string tlm_copyright_string;
inline const char* tlm_release();
inline const char* tlm_version();
inline const char* tlm_copyright();
} // namespace tlm

10.8.3 Rules
10.8.3 规则
a)
Each implementation-defined_number shall consist of a sequence of decimal digits 
from the character set [0–9] not enclosed in quotation marks.
a)每一个实现中定义的数字,应该由0到9之间的十进制字符序列构成,而且不用双引号括起来。

b) The originator and pre-release strings shall each consist of a sequence of characters 
from the character set [A–Z][a–z][0–9]_ enclosed in quotation marks.

c) The version release date shall consist of an ISO 8601 basic format calendar date of the form 
YYYYMMDD, where each of the eight characters is a decimal digit, enclosed in quotation marks.

d) The TLM_IS_PRERELEASE flag shall be either 0 or 1, not enclosed in quotation marks.

e) The version string shall be set to the value "major.minor.patch_prerelease-originator" or
"major.minor.patch-originator", where major, minor, patch, prerelease, and originator are the values
of the corresponding strings (without enclosing quotation marks), and the presence or absence of the
prerelease string shall depend on the value of the TLM_IS_PRERELEASE flag.

f) The copyright string should be set to a copyright notice.

g) Each constant shall be initialized with the value defined by the macro of the corresponding name converted to the appropriate data type.

h) The methods tlm_release and tlm_version shall each return the value of the version string converted to a C string.

i) The method tlm_copyright shall return the value of the copyright string converted to a C string.

翻译 第10章 of IEEE Std 1666-2011 IEEE Standard for Standard SystemC Language Reference Manual相关推荐

  1. 翻译 第11章 of IEEE Std 1666-2011 IEEE Standard for Standard SystemC Language Reference Manual

    11. TLM-2.0 core interfaces 11. TLM-2.0 核心接口 In addition to the core interfaces from TLM-1, TLM-2.0 ...

  2. Box2D v2.1.0用户手册翻译 - 第10章 世界(World Class)

    内容很多摘自 Aman JIANG(江超宇)翻译的Box2D v2.0.1 用户手册 第10章 世界(World Class) 关于 b2World类包含物体和关节.它管理着模拟的方方面面,并允许异步 ...

  3. Multi-AP Specification V2.0 中文翻译 第10章 Link metric collection(链路度量采集)

    Multi-AP Specification下载地址:https://www.wi-fi.org/download.php?file=/sites/default/files/private/Mult ...

  4. 翻译连载 | 第 10 章:异步的函数式(下)-《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇...

    为什么80%的码农都做不了架构师?>>>    原文地址:Functional-Light-JS 原文作者:Kyle Simpson-<You-Dont-Know-JS> ...

  5. 《Programming WPF》翻译 第8章 2.Timeline

    <Programming WPF>翻译 第8章 2.Timeline 原文:<Programming WPF>翻译 第8章 2.Timeline Timeline代表了时间的延 ...

  6. JTAG 标准IEEE STD 1149.1-2013学习笔记(三)Test data registers

    文章目录 一.TDR的实现 二.Bypass Register 三.Boundary-scan register 注:转载请注明出处 参考JTAG标准第九章测试数据寄存器(Test data regi ...

  7. 《Programming WPF》翻译 第7章 3.笔刷和钢笔

    原文:<Programming WPF>翻译 第7章 3.笔刷和钢笔 为了在屏幕上绘制一个图形,WPF需要知道你想要为图形填充什么颜色以及如何绘制它的边框.WPF提供了一些Brush类型支 ...

  8. 《Programming WPF》翻译 第3章 2.处理输入

    原文:<Programming WPF>翻译 第3章 2.处理输入 在Windows应用程序中,又3种基本的用户输入形式:鼠标.键盘和手写板.同时,还有一种更高级输入方式,其可能来自快捷键 ...

  9. 《Programming WPF》翻译 第7章 4.转换

    <Programming WPF>翻译 第7章 4.转换 原文:<Programming WPF>翻译 第7章 4.转换 支持高分辨率显示是WPF中的重要样式.这是被部分地支持 ...

最新文章

  1. 人要懂得放下已经发生,却又无法改变的事情
  2. centos eclipse java_CentOS7 安装 Eclipse
  3. 2018年最实用机器学习项目Top 6(附开源链接)
  4. C++学习系列笔记(五)
  5. Spark源码分析之Master注册机制原理
  6. 第二十一章:变换(十四)
  7. Memset、Memcpy、Strcpy 的作用和区别(转)
  8. 左耳朵耗子:996不是福气,但努力就会成功么?
  9. 物联网服务器搭建记录,心得
  10. ABAP 中的搜索帮助
  11. GeekBand C++ 设计模式 第一周笔记
  12. 获取当周和上周的周一、周日时间
  13. native-JavaScript通信流程( 基于最新的 react native版本 )
  14. Font Awesome文字图标的使用
  15. 易經大意(10) 三和 韓長庚 著
  16. 绘图---带你熟练操作PS工具栏
  17. 享誉全球的 Java 经典著作《Java核心技术》
  18. [ZT]股市经验谈--入门篇
  19. Java根据模板生成PDF文件
  20. 使命召唤手游如何在电脑上玩 使命召唤手游模拟器教程

热门文章

  1. SOA (百度百科)
  2. CentOS7安装新字体
  3. Grunt 单独对css压缩并生成min.css文件
  4. 视频编码失真测度:SAD、SATD、SSD、MSE、PSNR
  5. 2016个人年终总结
  6. 关于VS找不到“服务器资源管理器”的问题
  7. HTTP Status 404 - Not Found的一种情况
  8. 2003服务器支持cpu数量,windows server 2003 标准版能用的cpu的数量是多少/
  9. 关于pig是否可以匹配中文字符
  10. Ubuntu 安装 亿图