<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Observations from Uppsala &#187; Cadence</title>
	<atom:link href="http://jakob.engbloms.se/archives/tag/cadence/feed" rel="self" type="application/rss+xml" />
	<link>http://jakob.engbloms.se</link>
	<description>Computer Technology: Simulation, Virtualization, Virtual Platforms, Embedded, Multicore and Multiprocessing (by Jakob Engblom)</description>
	<lastBuildDate>Sun, 29 Jan 2012 19:45:28 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
<image>
    <title>Observations from Uppsala</title>
    <url>http://jakob.engbloms.se/favicon.png</url>
    <link>http://jakob.engbloms.se</link>
    <width>32</width>
    <height>32</height>
    <description>Observations from Uppsala - http://jakob.engbloms.se</description>
    </image>		<item>
		<title>DAC 2009 Panel and Paper</title>
		<link>http://jakob.engbloms.se/archives/823?&#038;owa_medium=feed&#038;owa_sid=</link>
		<comments>http://jakob.engbloms.se/archives/823#comments</comments>
		<pubDate>Wed, 01 Jul 2009 12:38:58 +0000</pubDate>
		<dc:creator>Jakob</dc:creator>
				<category><![CDATA[appearances]]></category>
		<category><![CDATA[conferences]]></category>
		<category><![CDATA[EDA]]></category>
		<category><![CDATA[virtual platforms]]></category>
		<category><![CDATA[Cadence]]></category>
		<category><![CDATA[DAC]]></category>
		<category><![CDATA[hardware-software interface]]></category>
		<category><![CDATA[Jason Andrews]]></category>
		<category><![CDATA[Ross Dickson]]></category>
		<category><![CDATA[Wild West panel]]></category>

		<guid isPermaLink="false">http://jakob.engbloms.se/?p=823</guid>
		<description><![CDATA[The 46th Design Automation Conference (DAC) is coming up in San Francisco in the US, last week of July. For me, this will be the first time I ever go to DAC. I have been to a couple of Design Automation and Test Europe  (DATE) conferences before, but DAC is supposedly even bigger as an [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-824" style="margin: 5px;" title="46daclogo" src="http://jakob.engbloms.se/wp-content/uploads/2009/07/46daclogo.gif" alt="46daclogo" width="81" height="73" />The <a href="http://www.dac.com/46th/index.aspx">46th Design Automation Conference (DAC) </a>is coming up in San Francisco in the US, last week of July. For me, this will be the first time I ever go to DAC. I have been to a couple of <a href="http://www.date-conference.com/">Design Automation and Test Europe  (DATE) </a>conferences before, but DAC is supposedly even bigger as an event for the EDA and related communities. I have the honor to be on a panel this year, as well as co-authoring a paper on software validation.</p>
<p><span id="more-823"></span>The panel is called &#8220;<a href="http://www.dac.com/events/eventdetails.aspx?id=95-49">The Wild West: Conquest of Complex Hardware-Dependent Software Design</a>&#8220;, and takes place on Thursday, July 30, at 16.30, in room 131. We will be discussing hardware/software integration, multicore software, and other topics that I like. We will have a good mix of tool providers and tool users.</p>
<p>The paper is called &#8220;Design Flow for Embedded System Device Driver Development and Verification&#8221;, and is co-authored by me, Jason Andrews of Cadence, and my colleague Ross Dickson. It is presented in the user track session called &#8220;<span id="ctl00_Center_Content_Placeholder__lblEventTitle" class="sestitle"><a href="http://www.dac.com/events/eventdetails.aspx?id=95-3-U">Verification: A Front-End Perspective</a>&#8220;, on Tuesday, at 16.30. It deals with how you can use directed random testing to verify software drivers for custom hardware, using a virtual platform.<br />
</span></p>
<p>I will at the DAC all week, sounds like a great fun event!<span class="sestitle"><br />
</span></p>
<div class="simple_likebuttons_container_small">
      <div class="simple_likebuttons_googleplus">
        <g:plusone size="medium" count="false" href="http://jakob.engbloms.se/archives/823"></g:plusone>
      </div>
    
      <div class="simple_likebuttons_twitter simple_likebuttons_twitter_s">
        <a href="https://twitter.com/share" class="twitter-share-button" data-count="none" data-url="http://jakob.engbloms.se/archives/823" data-lang="en">Tweet</a>
      </div>
    
      <div class="simple_likebuttons_facebook">
        <div id="fb-root"></div>
        <script>(function(d, s, id) {
          var js, fjs = d.getElementsByTagName(s)[0];
          if (d.getElementById(id)) {return;}
          js = d.createElement(s); js.id = id;
          js.src = "//connect.facebook.net/en_US/all.js#xfbml=1";
          fjs.parentNode.insertBefore(js, fjs);
        }(document, "script", "facebook-jssdk"));</script>
        <div class="fb-like" data-href="http://jakob.engbloms.se/archives/823" data-send="false" data-layout="button_count" data-show-faces="false" data-width="90"></div>
      </div>
    </div>]]></content:encoded>
			<wfw:commentRss>http://jakob.engbloms.se/archives/823/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cadence SystemC Checkpointing</title>
		<link>http://jakob.engbloms.se/archives/817?&#038;owa_medium=feed&#038;owa_sid=</link>
		<comments>http://jakob.engbloms.se/archives/817#comments</comments>
		<pubDate>Sat, 13 Jun 2009 20:29:35 +0000</pubDate>
		<dc:creator>Jakob</dc:creator>
				<category><![CDATA[computer simulation technology]]></category>
		<category><![CDATA[virtual platforms]]></category>
		<category><![CDATA[Cadence]]></category>
		<category><![CDATA[Checkpointing]]></category>
		<category><![CDATA[George Frazier]]></category>
		<category><![CDATA[Simics]]></category>
		<category><![CDATA[SystemC]]></category>

		<guid isPermaLink="false">http://jakob.engbloms.se/?p=817</guid>
		<description><![CDATA[I while ago I wrote a blog post on checkpointing in virtual platforms, and what it is good for. Checkpointing has been a fairly rare feature in virtual platform tools for some reason, but it seems to be picking up some implementations. In particular, I recently noticed that Cadence added it to their simulator solutions [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-737" style="margin: 5px 10px;" title="gears1" src="http://jakob.engbloms.se/wp-content/uploads/2009/04/gears1.png" alt="gears1" width="56" height="57" />I while ago I wrote a blog post on <a href="http://jakob.engbloms.se/archives/714">checkpointing </a>in virtual platforms, and what it is good for. Checkpointing has been a fairly rare feature in virtual platform tools for some reason, but it seems to be picking up some implementations. In particular, I recently noticed that Cadence added it to their simulator solutions a while ago (2007 according to their blog posts). There are a two blog posts  by <a href="http://www.cadence.com/community/posts/georgef.aspx">George Frazier </a>of Cadence (&#8220;<a href="http://www.cadence.com/Community/blogs/sd/archive/2009/02/18/how-to-save-os-boot-time-in-your-systemc-virtual-platform-with-save-and-restore.aspx">saving boot time</a>&#8221; and &#8220;<a href="http://www.cadence.com/Community/blogs/sd/archive/2009/03/09/systemc-save-and-restore-part-2-advanced-usage.aspx">advanced usage</a>&#8220;) that offer some insight into what is going on.</p>
<p><span id="more-817"></span>Note that checkpointing is nothing new to RTL-level HDL simulators, since that is a much more controlled environment than a general virtual platform. I think the Cadence blog put it quite well:</p>
<blockquote><p><span id="anormal_12" class="Cadence_CS_BlogDetail_BlogText">Save and restore (or restart) has existed in HDL simulators for years, but things are trickier if SystemC is involved. For one thing, SystemC simulators use external tools for compilation and linking: i.e. gcc. They have more or less a “black box” understanding of global variables, local variables, file descriptors and heap values that make up the simulation state at any point in time. When you throw in multiple threads implemented with application-level threading packages and the fact that C++ heap objects are impractical to save programmatically, it’s easy to see why save and restore tools for HDL simulators can’t be easily extended for SystemC. </span></p></blockquote>
<p><span class="Cadence_CS_BlogDetail_BlogText">I could not say it better myself. What is interesting is that the Cadence solution does solve this problem, in a limitied way, for a limited use case. I have not looked at their solution in detail (such as using it myself), but this paragraph indicates that the solution is essentially a complete memory contents dump:</span></p>
<blockquote><p><span id="anormal_12" class="Cadence_CS_BlogDetail_BlogText">During restart, all internal variables inherit the same values from the process as it existed at the time of save (for example, C variables declared static). While this behavior helps assure that SystemC state information is properly saved and restored, it can also leave variables that reference the process environment (like file descriptor and sockets to other processes) in limbo. </span></p></blockquote>
<p><span class="Cadence_CS_BlogDetail_BlogText">Doing it this way is heroic in effort but also quite limited in scope. If I look at the four operations for restoring from a checkpoint that I outlined in my previous blog post on checkpointing:</span></p>
<ul>
<li><span class="Cadence_CS_BlogDetail_BlogText">Restore to same machine, same model</span></li>
<li><span class="Cadence_CS_BlogDetail_BlogText">Restore to different machine, same model</span></li>
<li><span class="Cadence_CS_BlogDetail_BlogText">Restore to same or different machine, updated model</span></li>
<li><span class="Cadence_CS_BlogDetail_BlogText">Restore to same or different machine, completely different model</span></li>
</ul>
<p>It is clear that you can only do the first, as the solution will restore the state of an implementation of a model, not just its relevant state as is done in Simics checkpointing. The sole advantage of this approach is that it does work with arbitrary code. But it does not support any of the more powerful uses of checkpoints beyond simply not repeating work for a single user on a particular machine.</p>
<p>I don&#8217;t think a memory dump can travel even to a second machine of similar make and setup, since it will depend on the precise memory layout of a process that starts. And that is affected by DLL and shared objects load order, which is hard to control. The versions of all libraries have to be exactly the same too. It is not even clear that a checkpoint survives the upgrading of the OS on the machine being used, as that will surely change things in terms of precise memory allocation.Would be happy for the Cadence users to be proven wrong, but in principle I think checkpointing done right requires models to be written explicitly to support it. <a href="http://stackoverflow.com/questions/184027/serialization-of-objects-no-thread-state-can-be-involved-right">Just like any serialization solution in any programming language</a>.</p>
<p>I must admit that George Frazier does mention using checkpoints &#8220;weeks or even months&#8221; after initial save, but there is no mention of changing the code of the model in that time frame. For me checkpoints tend to live for years, I have some nice Simics demo checkpoints that have been with us for some five years at this point in time, surviving from Simics 2.0 to 2.2 to 3.0 to 3.2 to 4.0 to 4.2&#8230; thanks to the power of the Simics &#8220;save only explicitly defined state&#8221; principle, and checkpoint updater functions that essentially rewrite old checkpoints to make them compatible with new and updated machine models.</p>
<p>The other bit that I find interesting is what is considered the biggest headache: not the actual saving of the memory state, but how to handle open files and similar host operating-system connections:</p>
<p><span id="anormal_12" class="Cadence_CS_BlogDetail_BlogText"></p>
<blockquote><p>If a save operation is performed when the file is open then problems can arise if the program attempts to write to the same file after restore (because the file descriptor associated with the open file will be in a different state after restore).</p></blockquote>
<p>It is nice to have a way to solve this, but it is also pretty shocking that you have to solve it! It kicks of a mini-rant&#8230; A virtual platform model should <em>not </em>read or write or access other host resources directly in any way, in my rulebook for sound programming practice. All host dependencies should be handled via the simulation core and framework, in a manner that is checkpoint-safe, portable, and does not rely on any information from the host directly in the models. It is crucial to localize all such host interactions in specially written host connection modules that make sure all regular simulation modules run in a completely encapsulated and virtual world.</p>
<p>So, overall, hats off to Cadence for actually doing something, but keep in mind that it will be very limited until some discipline is exercised in modeling and state considered as something separate from the implementation.</p>
<p></span></p>
<div class="simple_likebuttons_container_small">
      <div class="simple_likebuttons_googleplus">
        <g:plusone size="medium" count="false" href="http://jakob.engbloms.se/archives/817"></g:plusone>
      </div>
    
      <div class="simple_likebuttons_twitter simple_likebuttons_twitter_s">
        <a href="https://twitter.com/share" class="twitter-share-button" data-count="none" data-url="http://jakob.engbloms.se/archives/817" data-lang="en">Tweet</a>
      </div>
    
      <div class="simple_likebuttons_facebook">
        <div id="fb-root"></div>
        <script>(function(d, s, id) {
          var js, fjs = d.getElementsByTagName(s)[0];
          if (d.getElementById(id)) {return;}
          js = d.createElement(s); js.id = id;
          js.src = "//connect.facebook.net/en_US/all.js#xfbml=1";
          fjs.parentNode.insertBefore(js, fjs);
        }(document, "script", "facebook-jssdk"));</script>
        <div class="fb-like" data-href="http://jakob.engbloms.se/archives/817" data-send="false" data-layout="button_count" data-show-faces="false" data-width="90"></div>
      </div>
    </div>]]></content:encoded>
			<wfw:commentRss>http://jakob.engbloms.se/archives/817/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Cadence Industry Insight: &#8220;Virtual Platforms Unite HW and SW&#8221;</title>
		<link>http://jakob.engbloms.se/archives/784?&#038;owa_medium=feed&#038;owa_sid=</link>
		<comments>http://jakob.engbloms.se/archives/784#comments</comments>
		<pubDate>Fri, 22 May 2009 06:41:09 +0000</pubDate>
		<dc:creator>Jakob</dc:creator>
				<category><![CDATA[articles]]></category>
		<category><![CDATA[embedded software]]></category>
		<category><![CDATA[embedded systeme]]></category>
		<category><![CDATA[ESL]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[virtual platforms]]></category>
		<category><![CDATA[Cadence]]></category>
		<category><![CDATA[Domain-specific languages]]></category>
		<category><![CDATA[ISX]]></category>
		<category><![CDATA[Richard Goering]]></category>
		<category><![CDATA[scdsource]]></category>
		<category><![CDATA[software testing]]></category>

		<guid isPermaLink="false">http://jakob.engbloms.se/?p=784</guid>
		<description><![CDATA[Another Cadence guest blog entry, about the overall impact of virtual platforms on the interaction between hardware and software designers. Essentially, virtual platforms are a great tool to make software and hardware people talk to each other more, since it provides a common basis for understanding. My entry is called &#8220;Virtual Platforms unites Hardware, Software [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-654" style="margin-left: 5px; margin-right: 5px;" title="opinion" src="http://jakob.engbloms.se/wp-content/uploads/2009/02/opinion.png" alt="opinion" width="91" height="69" />Another Cadence guest blog entry, about the overall impact of virtual platforms on the interaction between hardware and software designers. Essentially, virtual platforms are a great tool to make software and hardware people talk to each other more, since it provides a common basis for understanding.</p>
<p><span id="more-784"></span>My entry is called &#8220;<a href="http://www.cadence.com/Community/blogs/ii/archive/2009/05/21/guest-blog-virtual-platforms-unite-hardware-software-designers.aspx">Virtual Platforms unites Hardware, Software Engineers</a>&#8220;, and is presented by <a href="http://www.cadence.com/community/posts/rgoering.aspx">Richard Goering </a>(who used to be with <a href="http://www.scdsource.com">SCDSource</a>), in his &#8220;<a href="http://www.cadence.com/Community/blogs/ii/default.aspx">Industry Insights</a>&#8221; section of the Cadence community of blogs. Richard Goering has a personal post pointing in the same direction, about <a href="http://www.cadence.com/Community/blogs/ii/archive/2009/05/13/meeting-the-embedded-software-challenge.aspx?postID=17593">EDA tackling embedded software</a>. Worth reading.</p>
<p>Note that I do <em>not </em>say that hardware and software engineers should use the same <em>programming languages</em> as a result of using virtual platforms. Programming languages efficient for hardware design are quite different from those efficient for virtual platform creation, which are in turn different from good software engineering languages.  In some cases, some of them coincide, but in general, I believe in using the best tool for each job, and a programming language is just a tool. And the more designed it is for its task, the better. Some older posts of mine on this topic:</p>
<ul>
<li><a href="http://jakob.engbloms.se/archives/747">DSL: Purpose-built languages</a></li>
<li><a href="http://jakob.engbloms.se/archives/681">DSL: The tyranny of syntax</a></li>
<li><a href="http://jakob.engbloms.se/archives/283">Multicore programming and DSLs</a></li>
<li><a href="http://jakob.engbloms.se/archives/165">What is the obsession with C in EDA?</a></li>
<li><a href="http://jakob.engbloms.se/archives/157">Kunle Olukotun on DSLs</a></li>
<li><a href="http://jakob.engbloms.se/archives/709">Modeling hardware at a high level for software development</a></li>
</ul>
<p>And there is the <a href="http://jakob.engbloms.se/archives/306">ChipDesign article </a>from last year about using virtual platforms in the hardware design process all the way out to customers.</p>
<div class="simple_likebuttons_container_small">
      <div class="simple_likebuttons_googleplus">
        <g:plusone size="medium" count="false" href="http://jakob.engbloms.se/archives/784"></g:plusone>
      </div>
    
      <div class="simple_likebuttons_twitter simple_likebuttons_twitter_s">
        <a href="https://twitter.com/share" class="twitter-share-button" data-count="none" data-url="http://jakob.engbloms.se/archives/784" data-lang="en">Tweet</a>
      </div>
    
      <div class="simple_likebuttons_facebook">
        <div id="fb-root"></div>
        <script>(function(d, s, id) {
          var js, fjs = d.getElementsByTagName(s)[0];
          if (d.getElementById(id)) {return;}
          js = d.createElement(s); js.id = id;
          js.src = "//connect.facebook.net/en_US/all.js#xfbml=1";
          fjs.parentNode.insertBefore(js, fjs);
        }(document, "script", "facebook-jssdk"));</script>
        <div class="fb-like" data-href="http://jakob.engbloms.se/archives/784" data-send="false" data-layout="button_count" data-show-faces="false" data-width="90"></div>
      </div>
    </div>]]></content:encoded>
			<wfw:commentRss>http://jakob.engbloms.se/archives/784/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Guest Blog at Cadence: &#8220;Way Worse than the Real Thing&#8221;</title>
		<link>http://jakob.engbloms.se/archives/781?&#038;owa_medium=feed&#038;owa_sid=</link>
		<comments>http://jakob.engbloms.se/archives/781#comments</comments>
		<pubDate>Wed, 20 May 2009 10:45:21 +0000</pubDate>
		<dc:creator>Jakob</dc:creator>
				<category><![CDATA[articles]]></category>
		<category><![CDATA[computer simulation technology]]></category>
		<category><![CDATA[embedded software]]></category>
		<category><![CDATA[ESL]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[virtual platforms]]></category>
		<category><![CDATA[Cadence]]></category>
		<category><![CDATA[ISX]]></category>
		<category><![CDATA[Simics]]></category>
		<category><![CDATA[software testing]]></category>
		<category><![CDATA[Virtutech]]></category>

		<guid isPermaLink="false">http://jakob.engbloms.se/?p=781</guid>
		<description><![CDATA[Virtutech and Cadence yesterday announced the integration of Virtutech Simics and Cadence ISX (Incisive Software Extensions), which is essentially a directed random test framework for software. With this tool integration, you can systematically test low-level software and the hardware-software (device driver) interface of a system, leveraging a virtual platform. As part of explaining why this [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-782" style="margin-left: 5px; margin-right: 5px;" title="avataraspx" src="http://jakob.engbloms.se/wp-content/uploads/2009/05/avataraspx.jpg" alt="avataraspx" width="72" height="72" />Virtutech and Cadence yesterday announced the integration of Virtutech Simics and Cadence ISX (Incisive Software Extensions), which is essentially a directed random test framework for software. With this tool integration, you can systematically test low-level software and the hardware-software (device driver) interface of a system, leveraging a virtual platform.</p>
<p><span id="more-781"></span></p>
<p>As part of explaining why this is cool and what it means, I have a <a href="http://www.cadence.com/Community/blogs/sd/archive/2009/05/18/way-worse-than-the-real-thing.aspx">guest blog posting over at Cadence&#8217;s blog site</a>, called &#8220;Way Worse than the Real Thing&#8221;. The blog is posted under the general &#8220;TeamESL&#8221; &#8220;personality&#8221; on the blog site, which is used for people external to Cadence in the ESL space.</p>
<div class="simple_likebuttons_container_small">
      <div class="simple_likebuttons_googleplus">
        <g:plusone size="medium" count="false" href="http://jakob.engbloms.se/archives/781"></g:plusone>
      </div>
    
      <div class="simple_likebuttons_twitter simple_likebuttons_twitter_s">
        <a href="https://twitter.com/share" class="twitter-share-button" data-count="none" data-url="http://jakob.engbloms.se/archives/781" data-lang="en">Tweet</a>
      </div>
    
      <div class="simple_likebuttons_facebook">
        <div id="fb-root"></div>
        <script>(function(d, s, id) {
          var js, fjs = d.getElementsByTagName(s)[0];
          if (d.getElementById(id)) {return;}
          js = d.createElement(s); js.id = id;
          js.src = "//connect.facebook.net/en_US/all.js#xfbml=1";
          fjs.parentNode.insertBefore(js, fjs);
        }(document, "script", "facebook-jssdk"));</script>
        <div class="fb-like" data-href="http://jakob.engbloms.se/archives/781" data-send="false" data-layout="button_count" data-show-faces="false" data-width="90"></div>
      </div>
    </div>]]></content:encoded>
			<wfw:commentRss>http://jakob.engbloms.se/archives/781/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cadence-Ran vs Synopsys-Frank over Low-Power and Virtual Things</title>
		<link>http://jakob.engbloms.se/archives/344?&#038;owa_medium=feed&#038;owa_sid=</link>
		<comments>http://jakob.engbloms.se/archives/344#comments</comments>
		<pubDate>Sat, 15 Nov 2008 22:32:11 +0000</pubDate>
		<dc:creator>Jakob</dc:creator>
				<category><![CDATA[EDA]]></category>
		<category><![CDATA[ESL]]></category>
		<category><![CDATA[virtual platforms]]></category>
		<category><![CDATA[blog commentary]]></category>
		<category><![CDATA[Cadence]]></category>
		<category><![CDATA[Frank Schirrmeister]]></category>
		<category><![CDATA[power analysis]]></category>
		<category><![CDATA[Ran Avinun]]></category>
		<category><![CDATA[simulation]]></category>
		<category><![CDATA[Synopsys]]></category>

		<guid isPermaLink="false">http://jakob.engbloms.se/?p=344</guid>
		<description><![CDATA[Over the past few weeks there was a interesting exchange of blog posts, opinions, and ideas between Frank Schirrmeister of Synopsys and Ran Avinun of Cadence. It is about virtual platforms vs hardware emulation, and how to do low-power design &#8220;properly&#8221;. Quite an interesting exchange, and I think that Frank is a bit more right [...]]]></description>
			<content:encoded><![CDATA[<p>Over the past few weeks there was a interesting exchange of blog posts, opinions, and ideas between Frank Schirrmeister of Synopsys and Ran Avinun of Cadence. It is about virtual platforms vs hardware emulation, and how to do low-power design &#8220;properly&#8221;. Quite an interesting exchange, and I think that Frank is a bit more right in his thinking about virtual platforms and how to use them. Read on for some comments on the exchange.</p>
<p><span id="more-344"></span><br />
The following appears to be to sequence of events:</p>
<ul>
<li>Cadence press release, in September, about their &#8220;<a href="http://www.design-reuse.com/news/19019/power-analysis-pre-rtl-exploration.html">Palladium Incisive Palladium Dynamic Power Analysis and Cadence InCyte Chip Estimator</a>&#8220;, quoting Ran:</li>
<blockquote><p><em>Cadence Incisive Palladium Dynamic Power Analysis enables SoC designers, architects and validation engineers to quickly estimate the power consumption of their system during the design phase, analyzing the effects of running various real software stacks and other real-world stimuli. The new offerings also include the Cadence InCyte Chip Estimator, which can now provide what-if power analysis through exploration of different low-power techniques. The InCyte Chip Estimator also generates automatically the Si2 Common Power Format (CPF), which helps drive architectural power specification and intent into implementation and verification.</em></p></blockquote>
<li>Frank Schirrmeister blogged &#8220;<a href="http://www.synopsysoc.org/viewfromtop/?p=50">On Chameleons, Low Power and the Marketing Power of Copy Editing</a>&#8220;, basically saying that what Cadence was selling was something that was bound to the RTL level and thus arriving with estimates pretty late in the design process, after most important architecture decisions had been made. Instead, he proposed a flow using <strong>virtual prototypes </strong>that contained a sequence of successively better estimates, from the usual initial spreadsheet to estimates actually derived from RTL later in the process (or for IP blocks that already exist). Synopsys is not alone in this, <a href="http://www.neosera.com">Neosera </a>and <a href="http://www.scdsource.com/article.php?id=82">ChipVision</a> are after similar ideas. I think this approach makes excellent sense, following the idea that getting some kind of approximate feedback from a complete system early in the process is better than getting lots of details from a small part of a system late in the process.</li>
<li>Ran Avinun then blogged a reply to Frank, at &#8220;<a href="http://http://www.cadence.com/Community/blogs/sd/archive/2008/10/30/the-power-of-cadence-system-power-flow-vs-viewing-from-the-top.aspx">The Power of Cadence System Power Flow vs. Viewing from the Top</a>&#8220;. His contention there is that virtual prototypes have their uses, but that real designers will be using hardware accelerators, as that provides the key accuracy needed to do real power work. Also, he sees the creation of a virtual platform as a big problem, and cites a number of cases where running the actual semi-final RTL with power simulation was key to project success. Also, Ran sees the time needed to create a virtual platform as a big obstacle.</li>
<li>Frank then replied to the reply, at &#8220;<a href="http://www.synopsysoc.org/viewfromtop/?p=53">Hammers, Nails and the Spirits That I Called …</a>&#8220;&#8230; where he points out that Ran has some misconceptions about virtual platforms, admits that the Cadence flow works well, but that it does miss the point of early power estimation before the design is too frozen to be much changed. There is a pretty but hard-to-read diagram in the post, from <a href="http://www.design-reuse.com/articles/12728/towards-activity-based-system-level-power-estimation.html">a 2005 article he wrote while at ChipVision in Germany</a>, pointing out the need to evaluate designs with actual test data from the real world.</li>
</ul>
<p>What do I make of all of this?</p>
<h2>Ran&#8217;s Points</h2>
<p>I must admit that I think the Palladium hardware simulation accelerator boxes are very cool pieces of hardware, which at least used to be based on custom logic systems that use several cycles of a fixed sized hardware to simulate multiples of the hardware&#8217;s based emulation capacity (so 10M capacity system can use 10 cycles per target cycle to simulate 100M, for example). However, I do agree with Frank that these are dependent on having actual RTL in place to be of much use.</p>
<p>Another issue with hardware emulators is their overall availability: compared to the number of PCs available in an organization, they are going to be very limited. As discussed in many different forums, a key advantage of a pure virtual platform is that it can turn any programmer&#8217;s PC into a target system running the real target software. Without having to book time on a limited set of physical target machines, and hardware accelerators are such limited-in-supply hardware machines. So a virtual platform is much more available to people within, and especially outside, a design organization. Also, unless you are happy to release RTL for your design to people outside your organization, hardware acceleration is going to do little to help your end users get the most out of your design, pre-silicon.</p>
<p>My final gripe with hardware emulators is their limited scope. They tend to max out at a the borders of a single chip, or less. A virtual platform, on the other hand, has much more room to scale, to include multiple chips, <a href="http://www.virtutech.com/products/simics_accelerator.html">multiple boards</a>, or even <a href="http://www.compactpci-systems.com/articles/id/?3537">complete racks</a> and networks of networks. You cannot really do that in any hardware simulation, as it involves too many billions of gates running too many billions on instructions. The general rule of simulation still applies with hardware acceleration: <a href="http://www.engbloms.se/publications/engblom-ESC2008-class410-simulation-paper.pdf">you need to increase the level of abstraction to handle larger systems</a>.</p>
<p>As to the problem faced by Ran&#8217;s customers, having RTL but no virtual platform: what were they thinking of? Seriously, if you want to do design today a virtual platform should be your starting point, not an afterthought. Time and again, we see examples today where using virtual platforms <a href="http://www.chipdesignmag.com/display.php?articleId=2720&amp;issueId=31">gets chips to customers ahead of time and provides the ability to test ideas before committing to final RTL</a>. It seems that Ran agrees with this need, but his means are different:</p>
<blockquote><p><em>&#8220;As was stated above, big reason our customers use RTL emulation platforms is for accuracy, and while virtual platforms can offer certain performance, eventually the need to accuracy becomes critical and can not be overlooked, even for initial performance and power estimation analysis. Frank seems to forget in his statement above that the average bring-up time of new virtual platforms takes 6-12 months while the average bring-up time of many emulated designs takes days.&#8221;</em></p></blockquote>
<p>The time to create a virtual platform is actually pretty short, if you do it at a sufficently abstract level of detail and don&#8217;t worry too much about cycle accuracy. Also, that bringing up of an emulation depends on having a detailed RTL-level description to start with&#8230; which is not necessarily the case. I must say that the cited six to 12 months for a VP (for a single SoC as discussed here) sounds reasonable to me &#8212; if you are building a cycle-level model that tries to emulate the final timing (<a href="http://jakob.engbloms.se/archives/153">which might not be really feasible at at all</a>). If you work at a higher level of abstraction like loosely-timed TLM, that time shrinks by a factor of ten or so. I agree that in the end, accuracy is critical &#8211; but before you get there, the approximations used by the VP will have gotten you pretty far in terms of software development and architecture testing.</p>
<p>Ran is also afraid of the lack of accuracy:</p>
<blockquote><p><em><span id="anormal_12" class="Cadence_CS_BlogDetail_BlogText"> Now, even if you build this platform successfully 9-12 months in advance, how do you know that your virtual platform representing your real design? How do you connect it to your verification and implementation environment and realistic power information? Frank seems to overlook these things. Looking at the analogy of the story described at the blog above, using a system-level platform that is not targeting the actual hardware for performance analysis and power trade-offs guarantees that the Chamelon will become a snake and you will get bitten. </span></em></p></blockquote>
<p>As with all simulations, virtual platforms needs to be used with care and understanding. It might also once again be a matter of system scale: for RTL simulation, you are looking inside a single chip, and the detailed design to save power there. With a VP, you might be looking at whether a particular OS kernel does even care to try to turn off unused hardware at all&#8230; and that might be just as important in the end as being accurate in how functional units turn on and off inside an accelerator.</p>
<p>In today&#8217;s software-driven systems that mostly consist of existing off-the-shelf hardware, not any particular SoC that is being designed right now, the large-scale behavior and smarts of the software in a setting containing lots of chips and functions is far more important than optimizations inside a chip.</p>
<h2>Frank&#8217;s Points</h2>
<p>Since Frank is a virtual platform supporter just like me, I instinctively agree with his points about VPs being pretty fast to develop and available long in advance of actual silicon. I like the way he deals with power in the ARM DevCon presentation cited (do have a look at it), but still there are some lingering doubts and issues&#8230;</p>
<p>What I have a hard time understanding is just how detailed the virtual platforms need to be. The use of SystemC TLM-2.0 LT is sensible for speed, but it seems from the DevCon presentation that the main emphasis is on AT-level (and therefore pretty slow) timing-accurate simulations that look at power cycle by cycle in the target. If that is the case, I think we could almost just as well go get ourselves a hardware accelerator, as cycle-level models (even if transaction-driven)</p>
<p>However, Frank also says this which I cannot but agree with: you should not always run around with a hammer and look at everything like a nail &#8212; any reasonable chip design process needs both virtual platforms and hardware accelerators, one cannot really replace the other:</p>
<blockquote><p><em>When discussing this matter with a friend, he pointed out rightfully so that both Ran’s and my post suffer from “Hammer and Nail-itis”. In fact, he pointed out, the combination of Cadence’s estimators (InCyte), C based synthesis, Palladium, and Synopsys virtual would be pretty powerful! It’s a good thing then that we acquired Synplicity which brought us Synplify high-level synthesis and Confirma FPGA Prototyping to Synopsys, and of course, that we have existing interfaces between our Virtual Platforms and Eve’s solutions. </em></p></blockquote>
<h2>Conclusion</h2>
<p>To me, the lesson from this discussion is clear: A virtual platform should be the starting point of a new design, but once you get down to RTL, hardware acceleration is really pretty useful. You need both, and VP should come first, not second. It is not an either-or issue, rather I expect system and chip designers to use both tools, and the only question is what should come first, which I think is naturally the simulation in the form of a virtual platform. That also allows the chip to be set into a system context, which is otherwise pretty hard before silicon arrives, and something that large system integrators are screaming for.</p>
<div class="simple_likebuttons_container_small">
      <div class="simple_likebuttons_googleplus">
        <g:plusone size="medium" count="false" href="http://jakob.engbloms.se/archives/344"></g:plusone>
      </div>
    
      <div class="simple_likebuttons_twitter simple_likebuttons_twitter_s">
        <a href="https://twitter.com/share" class="twitter-share-button" data-count="none" data-url="http://jakob.engbloms.se/archives/344" data-lang="en">Tweet</a>
      </div>
    
      <div class="simple_likebuttons_facebook">
        <div id="fb-root"></div>
        <script>(function(d, s, id) {
          var js, fjs = d.getElementsByTagName(s)[0];
          if (d.getElementById(id)) {return;}
          js = d.createElement(s); js.id = id;
          js.src = "//connect.facebook.net/en_US/all.js#xfbml=1";
          fjs.parentNode.insertBefore(js, fjs);
        }(document, "script", "facebook-jssdk"));</script>
        <div class="fb-like" data-href="http://jakob.engbloms.se/archives/344" data-send="false" data-layout="button_count" data-show-faces="false" data-width="90"></div>
      </div>
    </div>]]></content:encoded>
			<wfw:commentRss>http://jakob.engbloms.se/archives/344/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cadence on Virtual Prototypes instead of Host Execution</title>
		<link>http://jakob.engbloms.se/archives/308?&#038;owa_medium=feed&#038;owa_sid=</link>
		<comments>http://jakob.engbloms.se/archives/308#comments</comments>
		<pubDate>Sun, 19 Oct 2008 21:40:37 +0000</pubDate>
		<dc:creator>Jakob</dc:creator>
				<category><![CDATA[computer simulation technology]]></category>
		<category><![CDATA[ESL]]></category>
		<category><![CDATA[virtual platforms]]></category>
		<category><![CDATA[virtualization]]></category>
		<category><![CDATA[blog commentary]]></category>
		<category><![CDATA[Cadence]]></category>

		<guid isPermaLink="false">http://jakob.engbloms.se/?p=308</guid>
		<description><![CDATA[Cadence technical blogger Jason Andrews wrote a short piece a couple of days ago on his perception that host-based execution is becoming unncessary thanks to fast virtual platforms. In &#8220;Is Host-Code Execution History&#8220;, he tells the story of a technique from long time ago where a target program was executed directly on the host, and [...]]]></description>
			<content:encoded><![CDATA[<p>Cadence technical blogger <a href="http://www.cadence.com/community/posts/jasona.aspx">Jason Andrews </a>wrote a short piece a couple of days ago on his perception that host-based execution is becoming unncessary thanks to fast virtual platforms. In &#8220;<a href="http://www.cadence.com/Community/blogs/sd/archive/2008/10/17/is-host-code-execution-history.aspx">Is Host-Code Execution History</a>&#8220;, he tells the story of a technique from long time ago where a target program was executed directly on the host, and memory accesses captured and passed to a Verilog simulator. The problem being solved was the lack of a simulator for the MIPS processor in use, and the solution was pretty fast and easy to use. Quite interesting, and well worth a read.</p>
<p>However, like all host-compiled execution (which I also like to call API-level simulation) it suffered from some problems, and virtual platforms today might offer the speed of host-compiled simulation without all the problems.</p>
<p><span id="more-308"></span></p>
<p>The problems are these:</p>
<blockquote><p><span id="anormal_12" class="Cadence_CS_BlogDetail_BlogText">Most companies that are using host-code execution today use &#8220;explicit access&#8221;.  This means they require all places in the code that access the hardware to call read() and write() functions so every hardware access goes through a common set of functions and then they use #ifdef to change the hardware accesses to call the simulator if they are doing verification with host-code execution. If they are running on the target system, then pointer dereferences are used. </span></p>
<p>&#8230;</p>
<p><span id="anormal_12" class="Cadence_CS_BlogDetail_BlogText">This is where implicit access came in. It provided a way to automatically trap pointer dereferences that were reading and writing to hardware locations and convert the load or store instruction into a simulated read or write. For reads it would put the result into the proper host CPU register and the user had no idea that a line of C code would magically turn into a bus transaction on a Verilog BFM</span></p></blockquote>
<p>Yes, that is a right pain, and I have seen lots of solutions for it, none of which have the elegant simplicity of a processor simulation. The &#8220;implicit access&#8221; system is basically trying to trap memory accesses without overtly changing the source code of a program. I guess the best way to do this is binary instrumentation, but it is still very hard to get to work right and robustly. A simulator is simply much simpler in principle here.</p>
<p>Jason continues later on:</p>
<blockquote><p><span id="anormal_12" class="Cadence_CS_BlogDetail_BlogText">Given the hassle of host-code execution I would prefer to cross compile the software and run the target instruction set. Beyond the implicit or explicit access issue, this also eliminates issues with differences in data type sizes, data structure layout, byte order (endianess) and other differences between the host and target processor. </span></p></blockquote>
<p>That is absolutely true! Jason does not mention the additional fun of what happens when the target is running an OS that is happily fielding interrupts, scheduling software tasks, etc. Also, that having to maintain a separate build target and maybe code variant is very expensive, process-wise. The expense that a good virtual platform incurs can be paid for pretty quickly once such reduced friction costs are factored in.</p>
<p>So I guess I pretty  much agree with all that Jason is saying, and thanks him for mentioning <a href="http://www.virtutech.com/products">Simics</a>. Thanks for the insights into what was done in the 1990s, it always interesting to get pointers to old fundamental and interesting work.</p>
<p>About how the virtual platforms actually work inside: it is not that complicated in principle (but pretty hairy to get it quite right and fast in practice). You have to simplify the timing of the target processor, you have to convert from target processor binaries to host binary format using some kind of just-in-time compilation technique (also called dynamic binary translation or code morphing), and you have to provide some kind of direct access to target memory for the target processor simulation (like the DMI feature in <a href="http://systemc.org">SystemC TLM-2.0</a>, but usually the difficult bits are on the CPU side of that, not the memory side).  The most interesting bit is how to build the surroundign system model to not slow the CPU model down, and for this I can recommend a couple of pieces of writing:</p>
<ul>
<li>My ESC 2008 general intro to the subject of virtual prototypes (<a href="http://www.engbloms.se/presentations/engblom-ESC2008-class410-simulation-slides.pdf">slides</a>, <a href="http://www.engbloms.se/publications/engblom-ESC2008-class410-simulation-paper.pdf">paper</a>)</li>
<li>Virtutech white paper on <a href="http://www.virtutech.com/whitepapers/modeling.html">system modeling </a></li>
</ul>
<div class="simple_likebuttons_container_small">
      <div class="simple_likebuttons_googleplus">
        <g:plusone size="medium" count="false" href="http://jakob.engbloms.se/archives/308"></g:plusone>
      </div>
    
      <div class="simple_likebuttons_twitter simple_likebuttons_twitter_s">
        <a href="https://twitter.com/share" class="twitter-share-button" data-count="none" data-url="http://jakob.engbloms.se/archives/308" data-lang="en">Tweet</a>
      </div>
    
      <div class="simple_likebuttons_facebook">
        <div id="fb-root"></div>
        <script>(function(d, s, id) {
          var js, fjs = d.getElementsByTagName(s)[0];
          if (d.getElementById(id)) {return;}
          js = d.createElement(s); js.id = id;
          js.src = "//connect.facebook.net/en_US/all.js#xfbml=1";
          fjs.parentNode.insertBefore(js, fjs);
        }(document, "script", "facebook-jssdk"));</script>
        <div class="fb-like" data-href="http://jakob.engbloms.se/archives/308" data-send="false" data-layout="button_count" data-show-faces="false" data-width="90"></div>
      </div>
    </div>]]></content:encoded>
			<wfw:commentRss>http://jakob.engbloms.se/archives/308/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>What&#8217;s the Obsession with C in EDA?</title>
		<link>http://jakob.engbloms.se/archives/165?&#038;owa_medium=feed&#038;owa_sid=</link>
		<comments>http://jakob.engbloms.se/archives/165#comments</comments>
		<pubDate>Wed, 23 Jul 2008 20:25:06 +0000</pubDate>
		<dc:creator>Jakob</dc:creator>
				<category><![CDATA[computer simulation technology]]></category>
		<category><![CDATA[embedded software]]></category>
		<category><![CDATA[ESL]]></category>
		<category><![CDATA[multicore software]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[C2S]]></category>
		<category><![CDATA[Cadence]]></category>
		<category><![CDATA[Catapult-C]]></category>
		<category><![CDATA[Cynthesizer]]></category>
		<category><![CDATA[Forte]]></category>
		<category><![CDATA[jokes]]></category>
		<category><![CDATA[Mentor]]></category>
		<category><![CDATA[parallelism]]></category>
		<category><![CDATA[rant]]></category>

		<guid isPermaLink="false">http://jakob.engbloms.se/?p=165</guid>
		<description><![CDATA[In early July, Cadence announced their new &#8220;C2S&#8221; C-to-silicon compiler. This event was marked with some excitement and blogging in the EDA space (SCDSource, EDN-Wilson, CDM-Martin, to give some links for more reading). At core, I agree that what they are doing is fairly cool &#8212; taking an essentially hardware-unrelated sequential program in C and [...]]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-166" style="margin: 10px;" title="whyc" src="http://jakob.engbloms.se/wp-content/uploads/2008/07/whyc.png" alt="" width="100" height="106" />In early July, Cadence announced their new &#8220;C2S&#8221; C-to-silicon compiler. This event was marked with some excitement and blogging in the EDA space (<a href="http://www.scdsource.com/article.php?id=270:">SCDSource</a>, <a href="http://www.edn.com/index.asp?layout=blog&amp;blog_id=1690000169&amp;blog_post_id=230029823">EDN-Wilson</a>, <a href="http://www.chipdesignmag.com/martins/2008/07/14/leibsons-law-in-action-cadence-returns-to-esl-with-new-synthesis-tool/">CDM-Martin</a>, to give some links for more reading). At core, I agree that what they are doing is fairly cool &#8212; taking an essentially hardware-unrelated sequential program in C and creating hardware from it. The kind of heavy technology that I have come to admire in the EDA space.</p>
<p>But I have to ask: why start with C?</p>
<p><span id="more-165"></span></p>
<h2>Productivity by Abstraction</h2>
<p>The motivation given in the marketing materials from Cadence is &#8220;productivity&#8221;, up to ten times more productivity or 90% of design time reduced. The key idea appears to be that C/C++/SystemC is more abstract than Verilog/VHDL, and therefore more design is produced in less time (<a href="http://www.cadence.com/rl/Resources/datasheets/C2Silicon_ds.pdf">see Cadence C2Silicon Datasheet</a>).</p>
<p>Similar (in spirit) products have similar motivations, with various numbers of how much better things are. For example, <a href="http://www.forteds.com/products/cynthesizer.asp">Forte&#8217;s Cynthesizer </a>claims &#8220;<em>2X-4X faster implementation from spec to netlist over RTL</em>&#8220;. <a href="http://www.mentor.com/products/esl/high_level_synthesis/catapult_synthesis/upload/Catapult_DS_0107.pdf"></a></p>
<p><a href="http://www.mentor.com/products/esl/high_level_synthesis/catapult_synthesis/upload/Catapult_DS_0107.pdf">Materials for Mentor&#8217;s Catapult </a>tool says it the best:</p>
<blockquote><p><em>Using industry standard pure ANSI C++ to describe functional intent, designers move up to a more productive abstraction level for designing complex ASIC or FPGA hardware typically found in next-generation, compute-intensive applications.</em></p></blockquote>
<p>And</p>
<blockquote><p><em>Single C++ source unites system designer and hardware designer</em></p></blockquote>
<p>So the idea from a large part of the EDA community seems to be that using a C-family language offers benefits of abstraction as well as a way to communicate with software people.</p>
<h2>Is C the Right Answer?</h2>
<p>What is funny with this obsession with raising the level of abstraction is that you keep ending up in the C family of languages. C, which is considered a &#8220;high-level assembler&#8221; by many people, and even worse, C++ which is a hard-to-parse semantic nightmare that most CS people that I know would rather do without.</p>
<p>I was reminded of an old joke from my early university CS days, about how to shoot yourself in the foot in various languages. The part on C++ is especially telling. From <a href="http://www-users.cs.york.ac.uk/susan/joke/foot.htm">http://www-users.cs.york.ac.uk/susan/joke/foot.htm</a>:</p>
<dl>
<blockquote><dt><em><strong>C</strong></em></dt>
<dd><em>You shoot yourself in the foot.</em></dd>
<dt><em><strong>C++</strong></em></dt>
<dd><em>You accidentally create a dozen instances of yourself and shoot them         all in the foot. Providing emergency medical assistance is impossible         since you can&#8217;t tell which are bitwise copies and which are just         pointing at others and saying &#8220;That&#8217;s me, over there.&#8221; </em></dd>
</blockquote>
</dl>
<p>So, putting on my Computer Science hat, I find the idea of using C as a raised level of abstraction would have been considered a bad joke when I was an undergraduate. In essence, C codies procedural programming as it was understood in the early 1970s, when compilers were very weak and a language that could do all that assembler could do was badly needed to write operating systems in a high-level language. In many ways, it was a step back compared to Pascal, Fortran, or Cobol. But it had the power to do anything, tended to result in faster code than other languages, and was available for more machines and operating systems than any other language. C++ then added objects (good), templates (good), but also tried to maintain the close-to-the-machine style of C (bad), multiple inheritance (complex), resulting in something very complex but decently useful and still being mostly like old C (despite having innumerable little detail differences in semantics compared to plain C).</p>
<p>So for a lot of good reasons, C/C++ is the de-facto standard language when you actually get down to the gritty job of getting a new language or operating system to run. It is the language to implement run-time systems, operating systems, new interpreted languages, etc. For the embedded space, C/C++ is often the only language available for a particular chip/OS combination. It is usually the best supported with the most compilers, the highest investment in compilers, and the most users of the compilers.</p>
<p>I have worked for a C compiler company called <a href="http://www.iar.se">IAR Systems</a>, and I appreciate the great engineering effort, skill, and pure intellectual fun that goes into creating C compilers that generate code that work well on resource-constrained embedded systems (doing C on an Intel 8051 is no mean feat). Compilers, that are good enough to wean embedded people off of assembly language.</p>
<p>But today, in general, I think that C/C++ is not the language anybody choses for a project if the goal is abstraction and greater productivity. Instead, you go for languages that are much more productive and that raises your productivity a few times over plain C/C++. Some typical examples:</p>
<ul>
<li>Languages that do away with memory management, like Java.</li>
<li>Languages that use virtual machine technology to ease porting across platforms, like Java, C#.net, Prolog, Python, Perl.</li>
<li>Languages that use dynamic typing or even duck typing, like Python and Ruby.</li>
<li>Languages that feature concurrency as a primary design features, like Erlang.</li>
<li>Functional languages with type inference, like ML and Haskell.</li>
<li>Graphical modeling tools that generate skeleton code, like UML.</li>
<li>Graphical domain-specific modeling tools that generate final code, like Matlab, Labview, and VisualState.</li>
<li>Constriant-resolution-based languages, like Oz.</li>
<li>Narrowly focused domain-specific languages, like CoWare LISA and Virtutech DML.</li>
<li>In-house very focused languages, usually not &#8220;Turing complete&#8221;.</li>
</ul>
<p>When I was studying CS, the basic assumption was that languages are tools, not religion. Any computer science major worth her or his salt should be able to learn any language in a short time, and you should use the language most appropriate for the task at hand. Using the same language all over the place because it is a &#8220;standard&#8221; is absolutely inefficient, from a software programming perspective.</p>
<p>In practice, large software systems in the embedded and desktop space tend to be constructed from around ten or so different languages (typically, you find C, C++, Java, some macro expanders like M4, string processing and file generation in perl, funky makefiles, some scripting in shell script, Python, VisualBasic, etc.). This is not anarchy, it is professionalism. If you asked a carpenter to use a hammer for all tasks, he would be pretty sad &#8212; different tools are good for different things, and it is the same with languages.</p>
<h2>So Why C in EDA?</h2>
<p>Today, EDA companies are moving from hardware design into partially software design, as SoC designs become more complex and software becomes a greater part of the overall system value. In this process, C/C++ and SystemC seem to be the language of choice.</p>
<p>I find this strange, considering the proud tradition of language inventions that you find in EDA. VHDL and Verilog were uniquely new things when they appeared, languages to describe hardware on hardware terms, and not software on instruction-set terms. Later, you have more abstract language like Bluespec and HandelC. There is a tradition, it seems, of very large and sophisticated compilers that take complicated inputs and transform them into hardware.</p>
<p>Using C/C++ as the input language really makes no technical sense, as it is very hard to parse and understand well in general. The restrictions imposed by the requirements of synthesis limits the C you can input quite severly, if you ask me.</p>
<p>If one idea for starting with C/C++ was to take a piece of &#8220;generic&#8221; source code and then compile it either to software or hardware, depending on system partitioning, I cannot see that working too well. Software-C tends to use constructs that are not appropriate for hardware synthesis like pointers and recursion. Hardware-C does not look likely to generate particuarly elegant or simple constructs when compiled to software.</p>
<p>So since the code is still going to be special for doing synthesis, why not use an altogether more elegant language? That seems to be what SystemVerilog is about to some extent, and what BlueSpec, for example, are doing. Or the tools to do hardware from UML.</p>
<p>I really do not understand how C/C++ came to be seen as the answer to what software is. Maybe because EDA companies tend to meet with the lowest-level software engineers? And these engineers are certainly only using C since they are running on very bare hardware and cannot assume the existence of rich run-time environment and virtual machines.</p>
<h2>Disciplined C</h2>
<p>Note that I do like the core idea of C-based synthesis, which is using C with restrictions, discipline, and coding patterns to ensure quality final code and communicate programmer intent to the compiler.</p>
<p>When I was with IAR, I taught several courses on how to get good small code out of an embedded C compiler (see for example <a href="http://www.engbloms.se/publications/engblom-esc-sf-2001.pdf">my ESC 2001 paper</a>). Basically, it comes down to writing &#8220;boring&#8221; C code that looks a whole lot like Pascal, and which does not rely on fancy semantic intricacies or old rules like using &#8220;which&#8221; rather than &#8220;for&#8221;. The <a href="http://www.imec.be/CleanC/">IMEC CleanC guidelines </a>are quite recent, but follow much of the same ideas to enable automatic parallelization of code for MPSoC designs.</p>
<p>But doing this is really a work-around for a poor initial language, if you look at the problem without preconceptions.</p>
<h2>The Sensible Starting Point</h2>
<p>What I think would make more sense is to start with some higher level of abstraction and then generate software code or hardware design from it.</p>
<p>This starting point should really be a parallel language, in some way, shape, or form. Using a sequential language like C as the starting point is fundamentally broken in this age of pervasive multicore systems. Future software will be written to run on parallel machines as the common case, and programs should expose the natural parallelism present in the problem being tackled. Taking a naturally parallel problem, packing it into disciplined sequential C, and then having a compiler discover the parallelism again is really a huge waste of effort.</p>
<p>The starting language might not necessarily be explicitly parallel (no need to scream about Occam or Ada tasking), it could just be domain-natural like Labview (which has been proven to be compilable down to parallel code). I do think that local memory + message passing + built-in task handling like Erlang looks like a very good approach for hardware design and software design, as it makes it possible to use sequential descriptions where they make sense and expose natural parallelism where it makes sense.</p>
<p>The starting language should also be as simple as possible in terms of how many different ways you can express things. In C, you can do &#8220;i++;&#8221;, &#8220;++i;&#8221;, &#8220;i+=1;&#8221;, &#8220;i=i+1;&#8221; to increment a variable. Why have more than one operation for this? The original point in C was to support various machine operations directly in the source language, as you could not trust the compiler to figure things out. Today, compilers can figure these things, so there is no point to be able to express the same thing in more than one very regular and easy-to-read way.</p>
<p>Another important aspect of modern software engineering is to support quick iterations, quick changes, and agile and extreme programming theories. This comes down to languages and environments that work even when systems are incomplete, and where it is easy to stub things out and later put in the details. C/C++ does not do this terribly well due to the use of static typing, static checking, and lack of default implementatioins for things which have not yet been filled in.</p>
<p>The language should also be designed to run on some virtual machine, as that helps portability and understanding programs. It also makes it a whole lot easier to write a reference compiler to integrate the language into simulation environments.</p>
<h2>Conclusion</h2>
<p>So where does this put me? I think these are my main points:</p>
<ul>
<li>C-to-hardware synthesis is pretty impressive technology</li>
<li>But why use C?</li>
<li>C is the EDA high-level darling</li>
<li>C is sequential and complicated</li>
<li>C is very low-level from the perspective of a software professional</li>
<li>A better input language should be concurrent/parallel and simple</li>
<li>A better input language should be designed for modern agile and extreme programming styles</li>
<li>EDA companies should really look at the leading edge of software engineering for inspiration, rather than what conservative embedded C programmers are doing.</li>
<li>VM-based languages are good</li>
</ul>
<p>I guess this goes into the &#8220;rant&#8221; bin&#8230;</p>
<p><!--[if gte mso 9]><xml> <w:WordDocument> <w:View>Normal</w:View> <w:Zoom>0</w:Zoom> <w:TrackMoves /> <w:TrackFormatting /> <w:PunctuationKerning /> <w:ValidateAgainstSchemas /> <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid> <w:IgnoreMixedContent>false</w:IgnoreMixedContent> <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText> <w:DoNotPromoteQF /> <w:LidThemeOther>EN-US</w:LidThemeOther> <w:LidThemeAsian>X-NONE</w:LidThemeAsian> <w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript> <w:Compatibility> <w:BreakWrappedTables /> <w:SnapToGridInCell /> <w:WrapTextWithPunct /> <w:UseAsianBreakRules /> <w:DontGrowAutofit /> <w:SplitPgBreakAndParaMark /> <w:DontVertAlignCellWithSp /> <w:DontBreakConstrainedForcedTables /> <w:DontVertAlignInTxbx /> <w:Word11KerningPairs /> <w:CachedColBalance /> </w:Compatibility> <w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel> <m:mathPr> <m:mathFont m:val="Cambria Math" /> <m:brkBin m:val="before" /> <m:brkBinSub m:val="&#45;-" /> <m:smallFrac m:val="off" /> <m:dispDef /> <m:lMargin m:val="0" /> <m:rMargin m:val="0" /> <m:defJc m:val="centerGroup" /> <m:wrapIndent m:val="1440" /> <m:intLim m:val="subSup" /> <m:naryLim m:val="undOvr" /> </m:mathPr></w:WordDocument> </xml><![endif]--><!--[if gte mso 9]><xml> <w:LatentStyles DefLockedState="false" DefUnhideWhenUsed="true"   DefSemiHidden="true" DefQFormat="false" DefPriority="99"   LatentStyleCount="267"> <w:LsdException Locked="false" Priority="0" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Normal" /> <w:LsdException Locked="false" Priority="9" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="heading 1" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 2" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 3" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 4" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 5" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 6" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 7" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 8" /> <w:LsdException Locked="false" Priority="9" QFormat="true" Name="heading 9" /> <w:LsdException Locked="false" Priority="39" Name="toc 1" /> <w:LsdException Locked="false" Priority="39" Name="toc 2" /> <w:LsdException Locked="false" Priority="39" Name="toc 3" /> <w:LsdException Locked="false" Priority="39" Name="toc 4" /> <w:LsdException Locked="false" Priority="39" Name="toc 5" /> <w:LsdException Locked="false" Priority="39" Name="toc 6" /> <w:LsdException Locked="false" Priority="39" Name="toc 7" /> <w:LsdException Locked="false" Priority="39" Name="toc 8" /> <w:LsdException Locked="false" Priority="39" Name="toc 9" /> <w:LsdException Locked="false" Priority="35" QFormat="true" Name="caption" /> <w:LsdException Locked="false" Priority="10" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Title" /> <w:LsdException Locked="false" Priority="1" Name="Default Paragraph Font" /> <w:LsdException Locked="false" Priority="11" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Subtitle" /> <w:LsdException Locked="false" Priority="22" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Strong" /> <w:LsdException Locked="false" Priority="20" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Emphasis" /> <w:LsdException Locked="false" Priority="59" SemiHidden="false"    UnhideWhenUsed="false" Name="Table Grid" /> <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Placeholder Text" /> <w:LsdException Locked="false" Priority="1" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="No Spacing" /> <w:LsdException Locked="false" Priority="60" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Shading" /> <w:LsdException Locked="false" Priority="61" SemiHidden="false"    UnhideWhenUsed="false" Name="Light List" /> <w:LsdException Locked="false" Priority="62" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Grid" /> <w:LsdException Locked="false" Priority="63" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 1" /> <w:LsdException Locked="false" Priority="64" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 2" /> <w:LsdException Locked="false" Priority="65" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 1" /> <w:LsdException Locked="false" Priority="66" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 2" /> <w:LsdException Locked="false" Priority="67" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 1" /> <w:LsdException Locked="false" Priority="68" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 2" /> <w:LsdException Locked="false" Priority="69" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 3" /> <w:LsdException Locked="false" Priority="70" SemiHidden="false"    UnhideWhenUsed="false" Name="Dark List" /> <w:LsdException Locked="false" Priority="71" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Shading" /> <w:LsdException Locked="false" Priority="72" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful List" /> <w:LsdException Locked="false" Priority="73" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Grid" /> <w:LsdException Locked="false" Priority="60" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Shading Accent 1" /> <w:LsdException Locked="false" Priority="61" SemiHidden="false"    UnhideWhenUsed="false" Name="Light List Accent 1" /> <w:LsdException Locked="false" Priority="62" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Grid Accent 1" /> <w:LsdException Locked="false" Priority="63" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 1 Accent 1" /> <w:LsdException Locked="false" Priority="64" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 2 Accent 1" /> <w:LsdException Locked="false" Priority="65" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 1 Accent 1" /> <w:LsdException Locked="false" UnhideWhenUsed="false" Name="Revision" /> <w:LsdException Locked="false" Priority="34" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="List Paragraph" /> <w:LsdException Locked="false" Priority="29" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Quote" /> <w:LsdException Locked="false" Priority="30" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Intense Quote" /> <w:LsdException Locked="false" Priority="66" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 2 Accent 1" /> <w:LsdException Locked="false" Priority="67" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 1 Accent 1" /> <w:LsdException Locked="false" Priority="68" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 2 Accent 1" /> <w:LsdException Locked="false" Priority="69" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 3 Accent 1" /> <w:LsdException Locked="false" Priority="70" SemiHidden="false"    UnhideWhenUsed="false" Name="Dark List Accent 1" /> <w:LsdException Locked="false" Priority="71" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Shading Accent 1" /> <w:LsdException Locked="false" Priority="72" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful List Accent 1" /> <w:LsdException Locked="false" Priority="73" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Grid Accent 1" /> <w:LsdException Locked="false" Priority="60" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Shading Accent 2" /> <w:LsdException Locked="false" Priority="61" SemiHidden="false"    UnhideWhenUsed="false" Name="Light List Accent 2" /> <w:LsdException Locked="false" Priority="62" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Grid Accent 2" /> <w:LsdException Locked="false" Priority="63" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 1 Accent 2" /> <w:LsdException Locked="false" Priority="64" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 2 Accent 2" /> <w:LsdException Locked="false" Priority="65" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 1 Accent 2" /> <w:LsdException Locked="false" Priority="66" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 2 Accent 2" /> <w:LsdException Locked="false" Priority="67" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 1 Accent 2" /> <w:LsdException Locked="false" Priority="68" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 2 Accent 2" /> <w:LsdException Locked="false" Priority="69" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 3 Accent 2" /> <w:LsdException Locked="false" Priority="70" SemiHidden="false"    UnhideWhenUsed="false" Name="Dark List Accent 2" /> <w:LsdException Locked="false" Priority="71" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Shading Accent 2" /> <w:LsdException Locked="false" Priority="72" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful List Accent 2" /> <w:LsdException Locked="false" Priority="73" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Grid Accent 2" /> <w:LsdException Locked="false" Priority="60" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Shading Accent 3" /> <w:LsdException Locked="false" Priority="61" SemiHidden="false"    UnhideWhenUsed="false" Name="Light List Accent 3" /> <w:LsdException Locked="false" Priority="62" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Grid Accent 3" /> <w:LsdException Locked="false" Priority="63" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 1 Accent 3" /> <w:LsdException Locked="false" Priority="64" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 2 Accent 3" /> <w:LsdException Locked="false" Priority="65" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 1 Accent 3" /> <w:LsdException Locked="false" Priority="66" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 2 Accent 3" /> <w:LsdException Locked="false" Priority="67" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 1 Accent 3" /> <w:LsdException Locked="false" Priority="68" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 2 Accent 3" /> <w:LsdException Locked="false" Priority="69" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 3 Accent 3" /> <w:LsdException Locked="false" Priority="70" SemiHidden="false"    UnhideWhenUsed="false" Name="Dark List Accent 3" /> <w:LsdException Locked="false" Priority="71" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Shading Accent 3" /> <w:LsdException Locked="false" Priority="72" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful List Accent 3" /> <w:LsdException Locked="false" Priority="73" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Grid Accent 3" /> <w:LsdException Locked="false" Priority="60" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Shading Accent 4" /> <w:LsdException Locked="false" Priority="61" SemiHidden="false"    UnhideWhenUsed="false" Name="Light List Accent 4" /> <w:LsdException Locked="false" Priority="62" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Grid Accent 4" /> <w:LsdException Locked="false" Priority="63" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 1 Accent 4" /> <w:LsdException Locked="false" Priority="64" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 2 Accent 4" /> <w:LsdException Locked="false" Priority="65" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 1 Accent 4" /> <w:LsdException Locked="false" Priority="66" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 2 Accent 4" /> <w:LsdException Locked="false" Priority="67" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 1 Accent 4" /> <w:LsdException Locked="false" Priority="68" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 2 Accent 4" /> <w:LsdException Locked="false" Priority="69" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 3 Accent 4" /> <w:LsdException Locked="false" Priority="70" SemiHidden="false"    UnhideWhenUsed="false" Name="Dark List Accent 4" /> <w:LsdException Locked="false" Priority="71" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Shading Accent 4" /> <w:LsdException Locked="false" Priority="72" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful List Accent 4" /> <w:LsdException Locked="false" Priority="73" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Grid Accent 4" /> <w:LsdException Locked="false" Priority="60" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Shading Accent 5" /> <w:LsdException Locked="false" Priority="61" SemiHidden="false"    UnhideWhenUsed="false" Name="Light List Accent 5" /> <w:LsdException Locked="false" Priority="62" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Grid Accent 5" /> <w:LsdException Locked="false" Priority="63" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 1 Accent 5" /> <w:LsdException Locked="false" Priority="64" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 2 Accent 5" /> <w:LsdException Locked="false" Priority="65" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 1 Accent 5" /> <w:LsdException Locked="false" Priority="66" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 2 Accent 5" /> <w:LsdException Locked="false" Priority="67" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 1 Accent 5" /> <w:LsdException Locked="false" Priority="68" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 2 Accent 5" /> <w:LsdException Locked="false" Priority="69" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 3 Accent 5" /> <w:LsdException Locked="false" Priority="70" SemiHidden="false"    UnhideWhenUsed="false" Name="Dark List Accent 5" /> <w:LsdException Locked="false" Priority="71" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Shading Accent 5" /> <w:LsdException Locked="false" Priority="72" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful List Accent 5" /> <w:LsdException Locked="false" Priority="73" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Grid Accent 5" /> <w:LsdException Locked="false" Priority="60" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Shading Accent 6" /> <w:LsdException Locked="false" Priority="61" SemiHidden="false"    UnhideWhenUsed="false" Name="Light List Accent 6" /> <w:LsdException Locked="false" Priority="62" SemiHidden="false"    UnhideWhenUsed="false" Name="Light Grid Accent 6" /> <w:LsdException Locked="false" Priority="63" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 1 Accent 6" /> <w:LsdException Locked="false" Priority="64" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Shading 2 Accent 6" /> <w:LsdException Locked="false" Priority="65" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 1 Accent 6" /> <w:LsdException Locked="false" Priority="66" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium List 2 Accent 6" /> <w:LsdException Locked="false" Priority="67" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 1 Accent 6" /> <w:LsdException Locked="false" Priority="68" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 2 Accent 6" /> <w:LsdException Locked="false" Priority="69" SemiHidden="false"    UnhideWhenUsed="false" Name="Medium Grid 3 Accent 6" /> <w:LsdException Locked="false" Priority="70" SemiHidden="false"    UnhideWhenUsed="false" Name="Dark List Accent 6" /> <w:LsdException Locked="false" Priority="71" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Shading Accent 6" /> <w:LsdException Locked="false" Priority="72" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful List Accent 6" /> <w:LsdException Locked="false" Priority="73" SemiHidden="false"    UnhideWhenUsed="false" Name="Colorful Grid Accent 6" /> <w:LsdException Locked="false" Priority="19" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Subtle Emphasis" /> <w:LsdException Locked="false" Priority="21" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Intense Emphasis" /> <w:LsdException Locked="false" Priority="31" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Subtle Reference" /> <w:LsdException Locked="false" Priority="32" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Intense Reference" /> <w:LsdException Locked="false" Priority="33" SemiHidden="false"    UnhideWhenUsed="false" QFormat="true" Name="Book Title" /> <w:LsdException Locked="false" Priority="37" Name="Bibliography" /> <w:LsdException Locked="false" Priority="39" QFormat="true" Name="TOC Heading" /> </w:LatentStyles> </xml><![endif]--> <!--[if gte mso 10]><br />
<mce:style><!   /* Style Definitions */  table.MsoNormalTable 	{mso-style-name:"Table Normal"; 	mso-tstyle-rowband-size:0; 	mso-tstyle-colband-size:0; 	mso-style-noshow:yes; 	mso-style-priority:99; 	mso-style-qformat:yes; 	mso-style-parent:""; 	mso-padding-alt:0cm 5.4pt 0cm 5.4pt; 	mso-para-margin:0cm; 	mso-para-margin-bottom:.0001pt; 	mso-pagination:widow-orphan; 	font-size:11.0pt; 	font-family:"Calibri","sans-serif";} --></p>
<p><!--[endif]--></p>
<div class="simple_likebuttons_container_small">
      <div class="simple_likebuttons_googleplus">
        <g:plusone size="medium" count="false" href="http://jakob.engbloms.se/archives/165"></g:plusone>
      </div>
    
      <div class="simple_likebuttons_twitter simple_likebuttons_twitter_s">
        <a href="https://twitter.com/share" class="twitter-share-button" data-count="none" data-url="http://jakob.engbloms.se/archives/165" data-lang="en">Tweet</a>
      </div>
    
      <div class="simple_likebuttons_facebook">
        <div id="fb-root"></div>
        <script>(function(d, s, id) {
          var js, fjs = d.getElementsByTagName(s)[0];
          if (d.getElementById(id)) {return;}
          js = d.createElement(s); js.id = id;
          js.src = "//connect.facebook.net/en_US/all.js#xfbml=1";
          fjs.parentNode.insertBefore(js, fjs);
        }(document, "script", "facebook-jssdk"));</script>
        <div class="fb-like" data-href="http://jakob.engbloms.se/archives/165" data-send="false" data-layout="button_count" data-show-faces="false" data-width="90"></div>
      </div>
    </div>]]></content:encoded>
			<wfw:commentRss>http://jakob.engbloms.se/archives/165/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
	</channel>
</rss>

